diff options
Diffstat (limited to 'OpenSim/Data/MSSQL/MSSQLManager.cs')
-rw-r--r-- | OpenSim/Data/MSSQL/MSSQLManager.cs | 529 |
1 files changed, 529 insertions, 0 deletions
diff --git a/OpenSim/Data/MSSQL/MSSQLManager.cs b/OpenSim/Data/MSSQL/MSSQLManager.cs new file mode 100644 index 0000000..efe62be --- /dev/null +++ b/OpenSim/Data/MSSQL/MSSQLManager.cs | |||
@@ -0,0 +1,529 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSim Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | using System.Data; | ||
31 | using System.Data.SqlClient; | ||
32 | using System.IO; | ||
33 | using System.Reflection; | ||
34 | using libsecondlife; | ||
35 | using OpenSim.Framework.Console; | ||
36 | |||
37 | namespace OpenSim.Framework.Data.MSSQL | ||
38 | { | ||
39 | /// <summary> | ||
40 | /// A management class for the MS SQL Storage Engine | ||
41 | /// </summary> | ||
42 | public class MSSQLManager | ||
43 | { | ||
44 | private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | ||
45 | |||
46 | /// <summary> | ||
47 | /// The database connection object | ||
48 | /// </summary> | ||
49 | private IDbConnection dbcon; | ||
50 | |||
51 | /// <summary> | ||
52 | /// Connection string for ADO.net | ||
53 | /// </summary> | ||
54 | private readonly string connectionString; | ||
55 | |||
56 | public MSSQLManager(string dataSource, string initialCatalog, string persistSecurityInfo, string userId, | ||
57 | string password) | ||
58 | { | ||
59 | connectionString = "Data Source=" + dataSource + ";Initial Catalog=" + initialCatalog + | ||
60 | ";Persist Security Info=" + persistSecurityInfo + ";User ID=" + userId + ";Password=" + | ||
61 | password + ";"; | ||
62 | dbcon = new SqlConnection(connectionString); | ||
63 | dbcon.Open(); | ||
64 | } | ||
65 | |||
66 | //private DataTable createRegionsTable() | ||
67 | //{ | ||
68 | // DataTable regions = new DataTable("regions"); | ||
69 | |||
70 | // createCol(regions, "regionHandle", typeof (ulong)); | ||
71 | // createCol(regions, "regionName", typeof (String)); | ||
72 | // createCol(regions, "uuid", typeof (String)); | ||
73 | |||
74 | // createCol(regions, "regionRecvKey", typeof (String)); | ||
75 | // createCol(regions, "regionSecret", typeof (String)); | ||
76 | // createCol(regions, "regionSendKey", typeof (String)); | ||
77 | |||
78 | // createCol(regions, "regionDataURI", typeof (String)); | ||
79 | // createCol(regions, "serverIP", typeof (String)); | ||
80 | // createCol(regions, "serverPort", typeof (String)); | ||
81 | // createCol(regions, "serverURI", typeof (String)); | ||
82 | |||
83 | |||
84 | // createCol(regions, "locX", typeof (uint)); | ||
85 | // createCol(regions, "locY", typeof (uint)); | ||
86 | // createCol(regions, "locZ", typeof (uint)); | ||
87 | |||
88 | // createCol(regions, "eastOverrideHandle", typeof (ulong)); | ||
89 | // createCol(regions, "westOverrideHandle", typeof (ulong)); | ||
90 | // createCol(regions, "southOverrideHandle", typeof (ulong)); | ||
91 | // createCol(regions, "northOverrideHandle", typeof (ulong)); | ||
92 | |||
93 | // createCol(regions, "regionAssetURI", typeof (String)); | ||
94 | // createCol(regions, "regionAssetRecvKey", typeof (String)); | ||
95 | // createCol(regions, "regionAssetSendKey", typeof (String)); | ||
96 | |||
97 | // createCol(regions, "regionUserURI", typeof (String)); | ||
98 | // createCol(regions, "regionUserRecvKey", typeof (String)); | ||
99 | // createCol(regions, "regionUserSendKey", typeof (String)); | ||
100 | |||
101 | // createCol(regions, "regionMapTexture", typeof (String)); | ||
102 | // createCol(regions, "serverHttpPort", typeof (String)); | ||
103 | // createCol(regions, "serverRemotingPort", typeof (uint)); | ||
104 | |||
105 | // // Add in contraints | ||
106 | // regions.PrimaryKey = new DataColumn[] {regions.Columns["UUID"]}; | ||
107 | // return regions; | ||
108 | //} | ||
109 | |||
110 | protected static void createCol(DataTable dt, string name, Type type) | ||
111 | { | ||
112 | DataColumn col = new DataColumn(name, type); | ||
113 | dt.Columns.Add(col); | ||
114 | } | ||
115 | |||
116 | protected static string defineTable(DataTable dt) | ||
117 | { | ||
118 | string sql = "create table " + dt.TableName + "("; | ||
119 | string subsql = String.Empty; | ||
120 | foreach (DataColumn col in dt.Columns) | ||
121 | { | ||
122 | if (subsql.Length > 0) | ||
123 | { | ||
124 | // a map function would rock so much here | ||
125 | subsql += ",\n"; | ||
126 | } | ||
127 | |||
128 | subsql += col.ColumnName + " " + SqlType(col.DataType); | ||
129 | if (col == dt.PrimaryKey[0]) | ||
130 | { | ||
131 | subsql += " primary key"; | ||
132 | } | ||
133 | } | ||
134 | sql += subsql; | ||
135 | sql += ")"; | ||
136 | return sql; | ||
137 | } | ||
138 | |||
139 | |||
140 | // this is something we'll need to implement for each db | ||
141 | // slightly differently. | ||
142 | public static string SqlType(Type type) | ||
143 | { | ||
144 | if (type == typeof(String)) | ||
145 | { | ||
146 | return "varchar(255)"; | ||
147 | } | ||
148 | else if (type == typeof(Int32)) | ||
149 | { | ||
150 | return "integer"; | ||
151 | } | ||
152 | else if (type == typeof(Double)) | ||
153 | { | ||
154 | return "float"; | ||
155 | } | ||
156 | else if (type == typeof(Byte[])) | ||
157 | { | ||
158 | return "image"; | ||
159 | } | ||
160 | else | ||
161 | { | ||
162 | return "varchar(255)"; | ||
163 | } | ||
164 | } | ||
165 | |||
166 | /// <summary> | ||
167 | /// Shuts down the database connection | ||
168 | /// </summary> | ||
169 | public void Close() | ||
170 | { | ||
171 | dbcon.Close(); | ||
172 | dbcon = null; | ||
173 | } | ||
174 | |||
175 | /// <summary> | ||
176 | /// Reconnects to the database | ||
177 | /// </summary> | ||
178 | public void Reconnect() | ||
179 | { | ||
180 | lock (dbcon) | ||
181 | { | ||
182 | try | ||
183 | { | ||
184 | // Close the DB connection | ||
185 | dbcon.Close(); | ||
186 | // Try reopen it | ||
187 | dbcon = new SqlConnection(connectionString); | ||
188 | dbcon.Open(); | ||
189 | } | ||
190 | catch (Exception e) | ||
191 | { | ||
192 | m_log.Error("Unable to reconnect to database " + e.ToString()); | ||
193 | } | ||
194 | } | ||
195 | } | ||
196 | |||
197 | /// <summary> | ||
198 | /// Runs a query with protection against SQL Injection by using parameterised input. | ||
199 | /// </summary> | ||
200 | /// <param name="sql">The SQL string - replace any variables such as WHERE x = "y" with WHERE x = @y</param> | ||
201 | /// <param name="parameters">The parameters - index so that @y is indexed as 'y'</param> | ||
202 | /// <returns>A Sql DB Command</returns> | ||
203 | public IDbCommand Query(string sql, Dictionary<string, string> parameters) | ||
204 | { | ||
205 | SqlCommand dbcommand = (SqlCommand)dbcon.CreateCommand(); | ||
206 | dbcommand.CommandText = sql; | ||
207 | foreach (KeyValuePair<string, string> param in parameters) | ||
208 | { | ||
209 | dbcommand.Parameters.AddWithValue(param.Key, param.Value); | ||
210 | } | ||
211 | |||
212 | return (IDbCommand)dbcommand; | ||
213 | } | ||
214 | |||
215 | /// <summary> | ||
216 | /// Runs a database reader object and returns a region row | ||
217 | /// </summary> | ||
218 | /// <param name="reader">An active database reader</param> | ||
219 | /// <returns>A region row</returns> | ||
220 | public RegionProfileData getRegionRow(IDataReader reader) | ||
221 | { | ||
222 | RegionProfileData regionprofile = new RegionProfileData(); | ||
223 | |||
224 | if (reader.Read()) | ||
225 | { | ||
226 | // Region Main | ||
227 | regionprofile.regionHandle = Convert.ToUInt64(reader["regionHandle"]); | ||
228 | regionprofile.regionName = (string)reader["regionName"]; | ||
229 | regionprofile.UUID = new LLUUID((string)reader["uuid"]); | ||
230 | |||
231 | // Secrets | ||
232 | regionprofile.regionRecvKey = (string)reader["regionRecvKey"]; | ||
233 | regionprofile.regionSecret = (string)reader["regionSecret"]; | ||
234 | regionprofile.regionSendKey = (string)reader["regionSendKey"]; | ||
235 | |||
236 | // Region Server | ||
237 | regionprofile.regionDataURI = (string)reader["regionDataURI"]; | ||
238 | regionprofile.regionOnline = false; // Needs to be pinged before this can be set. | ||
239 | regionprofile.serverIP = (string)reader["serverIP"]; | ||
240 | regionprofile.serverPort = Convert.ToUInt32(reader["serverPort"]); | ||
241 | regionprofile.serverURI = (string)reader["serverURI"]; | ||
242 | regionprofile.httpPort = Convert.ToUInt32(reader["serverHttpPort"]); | ||
243 | regionprofile.remotingPort = Convert.ToUInt32(reader["serverRemotingPort"]); | ||
244 | |||
245 | |||
246 | // Location | ||
247 | regionprofile.regionLocX = Convert.ToUInt32(reader["locX"]); | ||
248 | regionprofile.regionLocY = Convert.ToUInt32(reader["locY"]); | ||
249 | regionprofile.regionLocZ = Convert.ToUInt32(reader["locZ"]); | ||
250 | |||
251 | // Neighbours - 0 = No Override | ||
252 | regionprofile.regionEastOverrideHandle = Convert.ToUInt64(reader["eastOverrideHandle"]); | ||
253 | regionprofile.regionWestOverrideHandle = Convert.ToUInt64(reader["westOverrideHandle"]); | ||
254 | regionprofile.regionSouthOverrideHandle = Convert.ToUInt64(reader["southOverrideHandle"]); | ||
255 | regionprofile.regionNorthOverrideHandle = Convert.ToUInt64(reader["northOverrideHandle"]); | ||
256 | |||
257 | // Assets | ||
258 | regionprofile.regionAssetURI = (string)reader["regionAssetURI"]; | ||
259 | regionprofile.regionAssetRecvKey = (string)reader["regionAssetRecvKey"]; | ||
260 | regionprofile.regionAssetSendKey = (string)reader["regionAssetSendKey"]; | ||
261 | |||
262 | // Userserver | ||
263 | regionprofile.regionUserURI = (string)reader["regionUserURI"]; | ||
264 | regionprofile.regionUserRecvKey = (string)reader["regionUserRecvKey"]; | ||
265 | regionprofile.regionUserSendKey = (string)reader["regionUserSendKey"]; | ||
266 | try | ||
267 | { | ||
268 | regionprofile.owner_uuid = new LLUUID((string)reader["owner_uuid"]); | ||
269 | } | ||
270 | catch(Exception) | ||
271 | {} | ||
272 | // World Map Addition | ||
273 | string tempRegionMap = reader["regionMapTexture"].ToString(); | ||
274 | if (tempRegionMap != String.Empty) | ||
275 | { | ||
276 | regionprofile.regionMapTextureID = new LLUUID(tempRegionMap); | ||
277 | } | ||
278 | else | ||
279 | { | ||
280 | regionprofile.regionMapTextureID = new LLUUID(); | ||
281 | } | ||
282 | } | ||
283 | else | ||
284 | { | ||
285 | reader.Close(); | ||
286 | throw new Exception("No rows to return"); | ||
287 | } | ||
288 | return regionprofile; | ||
289 | } | ||
290 | |||
291 | /// <summary> | ||
292 | /// Reads a user profile from an active data reader | ||
293 | /// </summary> | ||
294 | /// <param name="reader">An active database reader</param> | ||
295 | /// <returns>A user profile</returns> | ||
296 | public UserProfileData readUserRow(IDataReader reader) | ||
297 | { | ||
298 | UserProfileData retval = new UserProfileData(); | ||
299 | |||
300 | if (reader.Read()) | ||
301 | { | ||
302 | retval.UUID = new LLUUID((string)reader["UUID"]); | ||
303 | retval.username = (string)reader["username"]; | ||
304 | retval.surname = (string)reader["lastname"]; | ||
305 | |||
306 | retval.passwordHash = (string)reader["passwordHash"]; | ||
307 | retval.passwordSalt = (string)reader["passwordSalt"]; | ||
308 | |||
309 | retval.homeRegion = Convert.ToUInt64(reader["homeRegion"].ToString()); | ||
310 | retval.homeLocation = new LLVector3( | ||
311 | Convert.ToSingle(reader["homeLocationX"].ToString()), | ||
312 | Convert.ToSingle(reader["homeLocationY"].ToString()), | ||
313 | Convert.ToSingle(reader["homeLocationZ"].ToString())); | ||
314 | retval.homeLookAt = new LLVector3( | ||
315 | Convert.ToSingle(reader["homeLookAtX"].ToString()), | ||
316 | Convert.ToSingle(reader["homeLookAtY"].ToString()), | ||
317 | Convert.ToSingle(reader["homeLookAtZ"].ToString())); | ||
318 | |||
319 | retval.created = Convert.ToInt32(reader["created"].ToString()); | ||
320 | retval.lastLogin = Convert.ToInt32(reader["lastLogin"].ToString()); | ||
321 | |||
322 | retval.userInventoryURI = (string)reader["userInventoryURI"]; | ||
323 | retval.userAssetURI = (string)reader["userAssetURI"]; | ||
324 | |||
325 | retval.profileCanDoMask = Convert.ToUInt32(reader["profileCanDoMask"].ToString()); | ||
326 | retval.profileWantDoMask = Convert.ToUInt32(reader["profileWantDoMask"].ToString()); | ||
327 | |||
328 | retval.profileAboutText = (string)reader["profileAboutText"]; | ||
329 | retval.profileFirstText = (string)reader["profileFirstText"]; | ||
330 | |||
331 | retval.profileImage = new LLUUID((string)reader["profileImage"]); | ||
332 | retval.profileFirstImage = new LLUUID((string)reader["profileFirstImage"]); | ||
333 | retval.webLoginKey = new LLUUID((string)reader["webLoginKey"]); | ||
334 | } | ||
335 | else | ||
336 | { | ||
337 | return null; | ||
338 | } | ||
339 | return retval; | ||
340 | } | ||
341 | |||
342 | /// <summary> | ||
343 | /// Reads an agent row from a database reader | ||
344 | /// </summary> | ||
345 | /// <param name="reader">An active database reader</param> | ||
346 | /// <returns>A user session agent</returns> | ||
347 | public UserAgentData readAgentRow(IDataReader reader) | ||
348 | { | ||
349 | UserAgentData retval = new UserAgentData(); | ||
350 | |||
351 | if (reader.Read()) | ||
352 | { | ||
353 | // Agent IDs | ||
354 | retval.UUID = new LLUUID((string)reader["UUID"]); | ||
355 | retval.sessionID = new LLUUID((string)reader["sessionID"]); | ||
356 | retval.secureSessionID = new LLUUID((string)reader["secureSessionID"]); | ||
357 | |||
358 | // Agent Who? | ||
359 | retval.agentIP = (string)reader["agentIP"]; | ||
360 | retval.agentPort = Convert.ToUInt32(reader["agentPort"].ToString()); | ||
361 | retval.agentOnline = Convert.ToBoolean(reader["agentOnline"].ToString()); | ||
362 | |||
363 | // Login/Logout times (UNIX Epoch) | ||
364 | retval.loginTime = Convert.ToInt32(reader["loginTime"].ToString()); | ||
365 | retval.logoutTime = Convert.ToInt32(reader["logoutTime"].ToString()); | ||
366 | |||
367 | // Current position | ||
368 | retval.currentRegion = (string)reader["currentRegion"]; | ||
369 | retval.currentHandle = Convert.ToUInt64(reader["currentHandle"].ToString()); | ||
370 | LLVector3.TryParse((string)reader["currentPos"], out retval.currentPos); | ||
371 | } | ||
372 | else | ||
373 | { | ||
374 | return null; | ||
375 | } | ||
376 | return retval; | ||
377 | } | ||
378 | |||
379 | public AssetBase getAssetRow(IDataReader reader) | ||
380 | { | ||
381 | AssetBase asset = new AssetBase(); | ||
382 | if (reader.Read()) | ||
383 | { | ||
384 | // Region Main | ||
385 | |||
386 | asset = new AssetBase(); | ||
387 | asset.Data = (byte[])reader["data"]; | ||
388 | asset.Description = (string)reader["description"]; | ||
389 | asset.FullID = new LLUUID((string)reader["id"]); | ||
390 | asset.InvType = Convert.ToSByte(reader["invType"]); | ||
391 | asset.Local = Convert.ToBoolean(reader["local"]); // ((sbyte)reader["local"]) != 0 ? true : false; | ||
392 | asset.Name = (string)reader["name"]; | ||
393 | asset.Type = Convert.ToSByte(reader["assetType"]); | ||
394 | } | ||
395 | else | ||
396 | { | ||
397 | return null; // throw new Exception("No rows to return"); | ||
398 | } | ||
399 | return asset; | ||
400 | } | ||
401 | |||
402 | |||
403 | /// <summary> | ||
404 | /// Inserts a new row into the log database | ||
405 | /// </summary> | ||
406 | /// <param name="serverDaemon">The daemon which triggered this event</param> | ||
407 | /// <param name="target">Who were we operating on when this occured (region UUID, user UUID, etc)</param> | ||
408 | /// <param name="methodCall">The method call where the problem occured</param> | ||
409 | /// <param name="arguments">The arguments passed to the method</param> | ||
410 | /// <param name="priority">How critical is this?</param> | ||
411 | /// <param name="logMessage">Extra message info</param> | ||
412 | /// <returns>Saved successfully?</returns> | ||
413 | public bool insertLogRow(string serverDaemon, string target, string methodCall, string arguments, int priority, | ||
414 | string logMessage) | ||
415 | { | ||
416 | string sql = "INSERT INTO logs ([target], [server], [method], [arguments], [priority], [message]) VALUES "; | ||
417 | sql += "(@target, @server, @method, @arguments, @priority, @message);"; | ||
418 | |||
419 | Dictionary<string, string> parameters = new Dictionary<string, string>(); | ||
420 | parameters["server"] = serverDaemon; | ||
421 | parameters["target"] = target; | ||
422 | parameters["method"] = methodCall; | ||
423 | parameters["arguments"] = arguments; | ||
424 | parameters["priority"] = priority.ToString(); | ||
425 | parameters["message"] = logMessage; | ||
426 | |||
427 | bool returnval = false; | ||
428 | |||
429 | try | ||
430 | { | ||
431 | IDbCommand result = Query(sql, parameters); | ||
432 | |||
433 | if (result.ExecuteNonQuery() == 1) | ||
434 | returnval = true; | ||
435 | |||
436 | result.Dispose(); | ||
437 | } | ||
438 | catch (Exception e) | ||
439 | { | ||
440 | m_log.Error(e.ToString()); | ||
441 | return false; | ||
442 | } | ||
443 | |||
444 | return returnval; | ||
445 | } | ||
446 | |||
447 | /// <summary> | ||
448 | /// Execute a SQL statement stored in a resource, as a string | ||
449 | /// </summary> | ||
450 | /// <param name="name"></param> | ||
451 | public void ExecuteResourceSql(string name) | ||
452 | { | ||
453 | SqlCommand cmd = new SqlCommand(getResourceString(name), (SqlConnection)dbcon); | ||
454 | cmd.ExecuteNonQuery(); | ||
455 | cmd.Dispose(); | ||
456 | } | ||
457 | |||
458 | public SqlConnection getConnection() | ||
459 | { | ||
460 | return (SqlConnection)dbcon; | ||
461 | } | ||
462 | |||
463 | /// <summary> | ||
464 | /// Given a list of tables, return the version of the tables, as seen in the database | ||
465 | /// </summary> | ||
466 | /// <param name="tableList"></param> | ||
467 | public void GetTableVersion(Dictionary<string, string> tableList) | ||
468 | { | ||
469 | lock (dbcon) | ||
470 | { | ||
471 | Dictionary<string, string> param = new Dictionary<string, string>(); | ||
472 | param["dbname"] = dbcon.Database; | ||
473 | IDbCommand tablesCmd = | ||
474 | Query("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_CATALOG=@dbname", param); | ||
475 | using (IDataReader tables = tablesCmd.ExecuteReader()) | ||
476 | { | ||
477 | while (tables.Read()) | ||
478 | { | ||
479 | try | ||
480 | { | ||
481 | string tableName = (string)tables["TABLE_NAME"]; | ||
482 | if (tableList.ContainsKey(tableName)) | ||
483 | tableList[tableName] = tableName; | ||
484 | } | ||
485 | catch (Exception e) | ||
486 | { | ||
487 | m_log.Error(e.ToString()); | ||
488 | } | ||
489 | } | ||
490 | tables.Close(); | ||
491 | } | ||
492 | } | ||
493 | } | ||
494 | |||
495 | private string getResourceString(string name) | ||
496 | { | ||
497 | Assembly assem = GetType().Assembly; | ||
498 | string[] names = assem.GetManifestResourceNames(); | ||
499 | |||
500 | foreach (string s in names) | ||
501 | if (s.EndsWith(name)) | ||
502 | using (Stream resource = assem.GetManifestResourceStream(s)) | ||
503 | { | ||
504 | using (StreamReader resourceReader = new StreamReader(resource)) | ||
505 | { | ||
506 | string resourceString = resourceReader.ReadToEnd(); | ||
507 | return resourceString; | ||
508 | } | ||
509 | } | ||
510 | throw new Exception(string.Format("Resource '{0}' was not found", name)); | ||
511 | } | ||
512 | |||
513 | /// <summary> | ||
514 | /// Returns the version of this DB provider | ||
515 | /// </summary> | ||
516 | /// <returns>A string containing the DB provider</returns> | ||
517 | public string getVersion() | ||
518 | { | ||
519 | Module module = GetType().Module; | ||
520 | string dllName = module.Assembly.ManifestModule.Name; | ||
521 | Version dllVersion = module.Assembly.GetName().Version; | ||
522 | |||
523 | |||
524 | return | ||
525 | string.Format("{0}.{1}.{2}.{3}", dllVersion.Major, dllVersion.Minor, dllVersion.Build, | ||
526 | dllVersion.Revision); | ||
527 | } | ||
528 | } | ||
529 | } | ||