1 // Copyright 2004-2007 Castle Project - http://www.castleproject.org/
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle
.ActiveRecord
.Framework
.Internal
18 using System
.Collections
;
19 using System
.Collections
.Specialized
;
21 using System
.Diagnostics
;
25 using NHibernate
.Connection
;
26 using NHibernate
.Dialect
;
29 /// Used to execute a script file to create/update/drop
30 /// a database schema. Inspired on NHibernate SchemaExport class.
32 public class ARSchemaCreator
34 private readonly IDictionary connectionProperties
;
35 private readonly Dialect dialect
;
38 /// Initializes a new instance of the <see cref="ARSchemaCreator"/> class.
40 /// <param name="config">The config.</param>
41 public ARSchemaCreator(Configuration config
)
43 this.connectionProperties
= config
.Properties
;
44 this.dialect
= Dialect
.GetDialect(connectionProperties
);
48 /// Executes the specified script file.
50 /// <param name="scriptFileName">Name of the script file.</param>
51 public void Execute(String scriptFileName
)
53 String
[] parts
= OpenFileAndStripContents(scriptFileName
);
58 private void ExecuteScript(String
[] parts
)
60 IConnectionProvider connectionProvider
=
61 ConnectionProviderFactory
.NewConnectionProvider(CreateConnectionProperties());
65 using(IDbConnection connection
= connectionProvider
.GetConnection())
67 ExecuteScriptParts(connection
, parts
);
72 throw new ActiveRecordException("Could not execute schema script", ex
);
77 /// Executes the script parts.
79 /// <param name="connection">The connection.</param>
80 /// <param name="parts">The parts.</param>
81 public static void ExecuteScriptParts(IDbConnection connection
, String
[] parts
)
83 using(IDbCommand statement
= connection
.CreateCommand())
85 foreach(String part
in parts
)
89 statement
.CommandText
= part
;
90 statement
.CommandType
= CommandType
.Text
;
91 statement
.ExecuteNonQuery();
95 // Ignored, but we output it
97 Console
.WriteLine(String
.Format("SQL: {0} \r\nthrew {1}. Ignoring", part
, ex
.Message
));
104 /// Opens the file and return an array of seperate commands that it contains
106 /// <param name="scriptFileName">Name of the script file.</param>
107 /// <returns></returns>
108 public static String
[] OpenFileAndStripContents(String scriptFileName
)
110 if (scriptFileName
== null)
112 throw new ArgumentNullException("scriptFileName");
115 scriptFileName
= Normalize(scriptFileName
);
117 if (!File
.Exists(scriptFileName
))
119 throw new ArgumentException("File name could not be found: " + scriptFileName
, "scriptFileName");
122 using(StreamReader reader
= new StreamReader(File
.OpenRead(scriptFileName
)))
124 String contents
= reader
.ReadToEnd();
126 String
[] parts
= contents
.Split(';');
128 if (parts
.Length
== 1)
130 parts
= SplitString(contents
, "GO");
137 private static String
[] SplitString(String sqlScript
, String split
)
139 ArrayList parts
= new ArrayList();
146 searchFrom
= sqlScript
.IndexOf(split
, searchFrom
+ 1);
148 if (searchFrom
!= -1)
150 parts
.Add(sqlScript
.Substring(lastIndex
, searchFrom
- lastIndex
));
152 lastIndex
= searchFrom
+ split
.Length
;
156 if (searchFrom
== -1 && lastIndex
!= 0)
158 parts
.Add(sqlScript
.Substring(lastIndex
));
165 return (String
[]) parts
.ToArray(typeof(String
));
168 private IDictionary
CreateConnectionProperties()
170 IDictionary props
= new HybridDictionary();
172 foreach(DictionaryEntry entry
in dialect
.DefaultProperties
)
174 props
[entry
.Key
] = entry
.Value
;
177 if (connectionProperties
!= null)
179 foreach(DictionaryEntry entry
in connectionProperties
)
181 props
[entry
.Key
] = entry
.Value
;
188 private static string Normalize(string fileName
)
190 if (!Path
.IsPathRooted(fileName
))
192 return Path
.Combine(AppDomain
.CurrentDomain
.BaseDirectory
, fileName
);