Mercurial > pub > bltoolkit
comparison Source/Data/DataProvider/DataProviderBase.cs @ 0:f990fcb411a9
Копия текущей версии из github
author | cin |
---|---|
date | Thu, 27 Mar 2014 21:46:09 +0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:f990fcb411a9 |
---|---|
1 using System; | |
2 using System.Collections.Generic; | |
3 using System.Data; | |
4 using System.Data.Common; | |
5 using System.Data.Linq; | |
6 using System.Linq; | |
7 | |
8 namespace BLToolkit.Data.DataProvider | |
9 { | |
10 using Common; | |
11 using Mapping; | |
12 using Sql.SqlProvider; | |
13 | |
14 /// <summary> | |
15 /// The <b>DataProviderBase</b> is a class that provides specific data provider information | |
16 /// for the <see cref="DbManager"/> class. | |
17 /// </summary> | |
18 /// <remarks> | |
19 /// See the <see cref="DbManager.AddDataProvider(DataProviderBase)"/> method to find an example. | |
20 /// </remarks> | |
21 /// <seealso cref="DbManager.AddDataProvider(DataProviderBase)">AddDataManager Method</seealso> | |
22 public abstract partial class DataProviderBase : IMappingSchemaProvider | |
23 { | |
24 #region Abstract Properties | |
25 | |
26 /// <summary> | |
27 /// Returns an actual type of the connection object used by this instance of the <see cref="DbManager"/>. | |
28 /// </summary> | |
29 /// <remarks> | |
30 /// See the <see cref="DbManager.AddDataProvider(DataProviderBase)"/> method to find an example. | |
31 /// </remarks> | |
32 /// <seealso cref="DbManager.AddDataProvider(DataProviderBase)">AddDataManager Method</seealso> | |
33 /// <value>An instance of the <see cref="Type"/> class.</value> | |
34 public abstract Type ConnectionType { get; } | |
35 | |
36 /// <summary> | |
37 /// Returns the data manager name. | |
38 /// </summary> | |
39 /// <remarks> | |
40 /// See the <see cref="DbManager.AddDataProvider(DataProviderBase)"/> method to find an example. | |
41 /// </remarks> | |
42 /// <seealso cref="DbManager.AddDataProvider(DataProviderBase)">AddDataManager Method</seealso> | |
43 /// <value>The data manager name.</value> | |
44 public abstract string Name { get; } | |
45 | |
46 private string _uniqueName; | |
47 /// <summary> | |
48 /// Same as <see cref="Name"/>, but may be overridden to add two or more providers of same type. | |
49 /// </summary> | |
50 public string UniqueName | |
51 { | |
52 get { return _uniqueName ?? Name; } | |
53 internal set { _uniqueName = value; } | |
54 } | |
55 | |
56 #endregion | |
57 | |
58 #region Abstract Methods | |
59 | |
60 /// <summary> | |
61 /// Creates a new instance of the <see cref="IDbConnection"/>. | |
62 /// </summary> | |
63 /// <remarks> | |
64 /// See the <see cref="DbManager.AddDataProvider(DataProviderBase)"/> method to find an example. | |
65 /// </remarks> | |
66 /// <seealso cref="DbManager.AddDataProvider(DataProviderBase)">AddDataManager Method</seealso> | |
67 /// <returns>The <see cref="IDbConnection"/> object.</returns> | |
68 public abstract IDbConnection CreateConnectionObject(); | |
69 | |
70 /// <summary> | |
71 /// Creates a new connection object with same connection string. | |
72 /// </summary> | |
73 /// <param name="connection">A connection object used as prototype.</param> | |
74 /// <returns>New connection instance.</returns> | |
75 public virtual IDbConnection CloneConnection(IDbConnection connection) | |
76 { | |
77 if (connection == null) | |
78 throw new ArgumentNullException("connection"); | |
79 | |
80 var cloneable = connection as ICloneable; | |
81 | |
82 if (cloneable != null) | |
83 return (IDbConnection)cloneable.Clone(); | |
84 | |
85 var newConnection = CreateConnectionObject(); | |
86 | |
87 // This is definitelly not enought when PersistSecurityInfo set to false. | |
88 // | |
89 newConnection.ConnectionString = connection.ConnectionString; | |
90 | |
91 return newConnection; | |
92 } | |
93 | |
94 /// <summary> | |
95 /// Creates an instance of the <see cref="DbDataAdapter"/>. | |
96 /// </summary> | |
97 /// <remarks> | |
98 /// See the <see cref="DbManager.AddDataProvider(DataProviderBase)"/> method to find an example. | |
99 /// </remarks> | |
100 /// <seealso cref="DbManager.AddDataProvider(DataProviderBase)">AddDataManager Method</seealso> | |
101 /// <returns>The <see cref="DbDataAdapter"/> object.</returns> | |
102 public abstract DbDataAdapter CreateDataAdapterObject(); | |
103 | |
104 /// <summary> | |
105 /// Populates the specified <see cref="IDbCommand"/> object's Parameters collection with | |
106 /// parameter information for the stored procedure specified in the <see cref="IDbCommand"/>. | |
107 /// </summary> | |
108 /// <remarks> | |
109 /// See the <see cref="DbManager.AddDataProvider(DataProviderBase)"/> method to find an example. | |
110 /// </remarks> | |
111 /// <seealso cref="DbManager.AddDataProvider(DataProviderBase)">AddDataManager Method</seealso> | |
112 /// <param name="command">The <see cref="IDbCommand"/> referencing the stored procedure | |
113 /// for which the parameter information is to be derived. | |
114 /// The derived parameters will be populated into the Parameters of this command.</param> | |
115 /// <returns>true - parameters can be derive.</returns> | |
116 public abstract bool DeriveParameters(IDbCommand command); | |
117 | |
118 #endregion | |
119 | |
120 #region Factory methods | |
121 | |
122 public virtual IDbCommand CreateCommandObject(IDbConnection connection) | |
123 { | |
124 return connection.CreateCommand(); | |
125 } | |
126 | |
127 public virtual IDbDataParameter CreateParameterObject(IDbCommand command) | |
128 { | |
129 return command.CreateParameter(); | |
130 } | |
131 | |
132 #endregion | |
133 | |
134 #region IDbDataParameter methods | |
135 | |
136 public virtual IDbDataParameter GetParameter( | |
137 IDbCommand command, | |
138 NameOrIndexParameter nameOrIndex) | |
139 { | |
140 return (IDbDataParameter)(nameOrIndex.ByName ? | |
141 command.Parameters[nameOrIndex.Name] : command.Parameters[nameOrIndex.Index]); | |
142 } | |
143 | |
144 public virtual void AttachParameter( | |
145 IDbCommand command, | |
146 IDbDataParameter parameter) | |
147 { | |
148 command.Parameters.Add(parameter); | |
149 } | |
150 | |
151 public virtual void SetUserDefinedType(IDbDataParameter parameter, string typeName) | |
152 { | |
153 throw new NotSupportedException(Name + " data provider does not support UDT."); | |
154 } | |
155 | |
156 public virtual bool IsValueParameter(IDbDataParameter parameter) | |
157 { | |
158 return parameter.Direction != ParameterDirection.ReturnValue; | |
159 } | |
160 | |
161 public virtual IDbDataParameter CloneParameter(IDbDataParameter parameter) | |
162 { | |
163 return (IDbDataParameter)((ICloneable)parameter).Clone(); | |
164 } | |
165 | |
166 public virtual bool InitParameter(IDbDataParameter parameter) | |
167 { | |
168 return false; | |
169 } | |
170 | |
171 #endregion | |
172 | |
173 #region Virtual Members | |
174 | |
175 /// <summary> | |
176 /// Open an <see cref="IDataReader"/> into the given RefCursor object | |
177 /// </summary> | |
178 /// <param name="refCursor">The refcursor to open an <see cref="IDataReader"/> to</param> | |
179 /// <returns>The <see cref="IDataReader"/> into the refcursor</returns> | |
180 public virtual IDataReader GetRefCursorDataReader(object refCursor) | |
181 { | |
182 throw new NotSupportedException("Operation not supported on this DataProvider"); | |
183 } | |
184 | |
185 public virtual object Convert(object value, ConvertType convertType) | |
186 { | |
187 return SqlProvider.Convert(value, convertType); | |
188 } | |
189 | |
190 public virtual DataExceptionType ConvertErrorNumberToDataExceptionType(int number) | |
191 { | |
192 return DataExceptionType.Undefined; | |
193 } | |
194 | |
195 public virtual void InitDbManager(DbManager dbManager) | |
196 { | |
197 var schema = MappingSchema; | |
198 | |
199 if (schema != null) | |
200 dbManager.MappingSchema = schema; | |
201 } | |
202 | |
203 /// <summary> | |
204 /// One time initialization from a configuration file. | |
205 /// </summary> | |
206 /// <param name="attributes">Provider specific attributes.</param> | |
207 public virtual void Configure(System.Collections.Specialized.NameValueCollection attributes) | |
208 { | |
209 } | |
210 | |
211 public virtual MappingSchema MappingSchema { get; set; } | |
212 | |
213 public virtual void PrepareCommand(ref CommandType commandType, ref string commandText, ref IDbDataParameter[] commandParameters) | |
214 { | |
215 /* | |
216 if (commandParameters != null) foreach (var p in commandParameters) | |
217 { | |
218 if (p.Value is System.Data.Linq.Binary) | |
219 { | |
220 var arr = ((System.Data.Linq.Binary)p.Value).ToArray(); | |
221 | |
222 p.Value = arr; | |
223 p.DbType = DbType.Binary; | |
224 p.Size = arr.Length; | |
225 } | |
226 } | |
227 */ | |
228 } | |
229 | |
230 public virtual bool CanReuseCommand(IDbCommand command, CommandType newCommandType) | |
231 { | |
232 return true; | |
233 } | |
234 | |
235 public virtual int ExecuteArray(IDbCommand command, int iterations) | |
236 { | |
237 // save parameter values | |
238 var parameters = command.Parameters | |
239 .OfType<IDbDataParameter>() | |
240 .Select(param => new | |
241 { | |
242 Parameter = param, | |
243 Value = param.Value as Array | |
244 }) | |
245 .ToArray(); | |
246 | |
247 var outParameters = parameters | |
248 .Where(p => | |
249 p.Parameter.Direction == ParameterDirection.InputOutput || | |
250 p.Parameter.Direction == ParameterDirection.Output) | |
251 .ToArray(); | |
252 | |
253 // validate parameter values | |
254 foreach (var p in parameters) | |
255 { | |
256 if (p.Value == null) | |
257 { | |
258 throw new InvalidOperationException("ExecuteArray requires that all " + | |
259 "parameter values are arrays. Parameter name: " + p.Parameter.ParameterName); | |
260 } | |
261 | |
262 if (p.Value.GetLength(0) != iterations) | |
263 { | |
264 throw new InvalidOperationException("ExecuteArray requires that array sizes are " + | |
265 "equal to the number of iterations. Parameter name: " + p.Parameter.ParameterName); | |
266 } | |
267 } | |
268 | |
269 try | |
270 { | |
271 // run iterations | |
272 int rowsAffected = 0; | |
273 for (int iteration = 0; iteration < iterations; iteration++) | |
274 { | |
275 // copy input parameter values | |
276 foreach (var param in parameters) | |
277 { | |
278 SetParameterValue(param.Parameter, param.Value.GetValue(iteration)); | |
279 } | |
280 | |
281 rowsAffected += command.ExecuteNonQuery(); | |
282 | |
283 // return output parameter values | |
284 foreach (var param in outParameters) | |
285 { | |
286 var outputValue = param.Parameter.Value; | |
287 param.Value.SetValue(outputValue, iteration); | |
288 } | |
289 } | |
290 | |
291 return rowsAffected; | |
292 } | |
293 finally | |
294 { | |
295 // restore parameter values | |
296 foreach (var param in parameters) | |
297 { | |
298 param.Parameter.Value = param.Value; | |
299 } | |
300 } | |
301 } | |
302 | |
303 public virtual string GetSequenceQuery(string sequenceName) | |
304 { | |
305 return null; | |
306 } | |
307 | |
308 public virtual string NextSequenceQuery(string sequenceName) | |
309 { | |
310 return null; | |
311 } | |
312 | |
313 public virtual string GetReturningInto(string columnName) | |
314 { | |
315 return null; | |
316 } | |
317 | |
318 public virtual void SetParameterValue(IDbDataParameter parameter, object value) | |
319 { | |
320 if (value is System.Data.Linq.Binary) | |
321 { | |
322 var arr = ((System.Data.Linq.Binary)value).ToArray(); | |
323 | |
324 parameter.Value = arr; | |
325 parameter.DbType = DbType.Binary; | |
326 parameter.Size = arr.Length; | |
327 } | |
328 else | |
329 parameter.Value = value; | |
330 } | |
331 | |
332 public abstract ISqlProvider CreateSqlProvider(); | |
333 | |
334 private ISqlProvider _sqlProvider; | |
335 protected ISqlProvider SqlProvider | |
336 { | |
337 get { return _sqlProvider ?? (_sqlProvider = CreateSqlProvider()); } | |
338 } | |
339 | |
340 public virtual IDataReader GetDataReader(MappingSchema schema, IDataReader dataReader) | |
341 { | |
342 return dataReader; | |
343 } | |
344 | |
345 public virtual IDataReader GetDataReader(IDbCommand command, CommandBehavior commandBehavior) | |
346 { | |
347 return command.ExecuteReader(commandBehavior); | |
348 } | |
349 | |
350 public virtual bool ParameterNamesEqual(string paramName1, string paramName2) | |
351 { | |
352 // default implementation is case-insensitive, because if we make it | |
353 // case-sensitive and don't overload it in all existing providers - client code may break | |
354 return string.Equals(paramName1, paramName2, StringComparison.OrdinalIgnoreCase); | |
355 } | |
356 | |
357 public virtual DbType GetDbType(Type systemType) | |
358 { | |
359 if (systemType == typeof(Binary) || systemType == typeof(byte[])) | |
360 return DbType.Binary; | |
361 | |
362 return DbType.Object; | |
363 } | |
364 | |
365 public virtual bool IsMarsEnabled(IDbConnection conn) | |
366 { | |
367 return false; | |
368 } | |
369 | |
370 public virtual string ProviderName { get { return ConnectionType.Namespace; } } | |
371 public virtual int MaxParameters { get { return 100; } } | |
372 public virtual int MaxBatchSize { get { return 65536; } } | |
373 public virtual string EndOfSql { get { return ";"; } } | |
374 | |
375 #endregion | |
376 | |
377 #region DataReaderEx | |
378 | |
379 protected class DataReaderBase<T> : IDataReader | |
380 where T: IDataReader | |
381 { | |
382 public readonly T DataReader; | |
383 | |
384 protected DataReaderBase(T rd) | |
385 { | |
386 DataReader = rd; | |
387 } | |
388 | |
389 #region Implementation of IDisposable | |
390 | |
391 public void Dispose() | |
392 { | |
393 DataReader.Dispose(); | |
394 } | |
395 | |
396 #endregion | |
397 | |
398 #region Implementation of IDataRecord | |
399 | |
400 public string GetName (int i) { return DataReader.GetName (i); } | |
401 public string GetDataTypeName(int i) { return DataReader.GetDataTypeName(i); } | |
402 public Type GetFieldType (int i) { return DataReader.GetFieldType (i); } | |
403 // GetValue method is virtual since it can be overridden by some data provider | |
404 // (For instance, OdbDataProvider uses special methodes for clob data fetching) | |
405 public virtual object GetValue (int i) { return DataReader.GetValue (i); } | |
406 public int GetValues (object[] values) { return DataReader.GetValues (values); } | |
407 public int GetOrdinal (string name) { return DataReader.GetOrdinal (name); } | |
408 public bool GetBoolean (int i) { return DataReader.GetBoolean (i); } | |
409 public byte GetByte (int i) { return DataReader.GetByte (i); } | |
410 public char GetChar (int i) { return DataReader.GetChar (i); } | |
411 public Guid GetGuid (int i) { return DataReader.GetGuid (i); } | |
412 public short GetInt16 (int i) { return DataReader.GetInt16 (i); } | |
413 public int GetInt32 (int i) { return DataReader.GetInt32 (i); } | |
414 public long GetInt64 (int i) { return DataReader.GetInt64 (i); } | |
415 public float GetFloat (int i) { return DataReader.GetFloat (i); } | |
416 public double GetDouble (int i) { return DataReader.GetDouble (i); } | |
417 public string GetString (int i) { return DataReader.GetString (i); } | |
418 public decimal GetDecimal (int i) { return DataReader.GetDecimal (i); } | |
419 public DateTime GetDateTime (int i) { return DataReader.GetDateTime (i); } | |
420 public IDataReader GetData (int i) { return DataReader.GetData (i); } | |
421 public bool IsDBNull (int i) { return DataReader.IsDBNull (i); } | |
422 | |
423 public int FieldCount { get { return DataReader.FieldCount; } } | |
424 | |
425 object IDataRecord.this[int i] { get { return DataReader[i]; } } | |
426 object IDataRecord.this[string name] { get { return DataReader[name]; } } | |
427 | |
428 public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length) | |
429 { | |
430 return DataReader.GetBytes(i, fieldOffset, buffer, bufferoffset, length); | |
431 } | |
432 | |
433 public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length) | |
434 { | |
435 return DataReader.GetChars(i, fieldoffset, buffer, bufferoffset, length); | |
436 } | |
437 | |
438 #endregion | |
439 | |
440 #region Implementation of IDataReader | |
441 | |
442 public void Close () { DataReader.Close (); } | |
443 public DataTable GetSchemaTable() { return DataReader.GetSchemaTable(); } | |
444 public bool NextResult () { return DataReader.NextResult (); } | |
445 public bool Read () { return DataReader.Read (); } | |
446 public int Depth { get { return DataReader.Depth; } } | |
447 public bool IsClosed { get { return DataReader.IsClosed; } } | |
448 public int RecordsAffected { get { return DataReader.RecordsAffected; } } | |
449 | |
450 #endregion | |
451 } | |
452 | |
453 protected abstract class DataReaderEx<T> : DataReaderBase<T>, IDataReaderEx | |
454 where T: IDataReader | |
455 { | |
456 protected DataReaderEx(T rd) : base(rd) | |
457 { | |
458 } | |
459 | |
460 #region Implementation of IDataReaderEx | |
461 | |
462 public abstract DateTimeOffset GetDateTimeOffset(int i); | |
463 | |
464 #endregion | |
465 } | |
466 | |
467 #endregion | |
468 | |
469 #region InsertBatch | |
470 | |
471 public virtual int InsertBatchWithIdentity<T>( | |
472 DbManager db, | |
473 string insertText, | |
474 IEnumerable<T> collection, | |
475 MemberMapper[] members, | |
476 int maxBatchSize, | |
477 DbManager.ParameterProvider<T> getParameters) | |
478 { | |
479 throw new NotImplementedException("Insert batch with identity is not implemented!"); | |
480 } | |
481 | |
482 public virtual int InsertBatch<T>( | |
483 DbManager db, | |
484 string insertText, | |
485 IEnumerable<T> collection, | |
486 MemberMapper[] members, | |
487 int maxBatchSize, | |
488 DbManager.ParameterProvider<T> getParameters) | |
489 { | |
490 db.SetCommand(insertText); | |
491 return db.ExecuteForEach(collection, members, maxBatchSize, getParameters); | |
492 } | |
493 | |
494 #endregion | |
495 | |
496 protected int ExecuteSqlList(DbManager db, IEnumerable<string> sqlList) | |
497 { | |
498 var cnt = 0; | |
499 | |
500 foreach (string sql in sqlList) | |
501 { | |
502 cnt += db.SetCommand(sql).ExecuteNonQuery(); | |
503 } | |
504 | |
505 return cnt; | |
506 } | |
507 | |
508 public virtual DbType GetParameterDbType(DbType dbType) | |
509 { | |
510 return dbType; | |
511 } | |
512 } | |
513 } |