diff Source/Data/DataProvider/DataProviderBase.cs @ 0:f990fcb411a9

Копия текущей версии из github
author cin
date Thu, 27 Mar 2014 21:46:09 +0400
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Source/Data/DataProvider/DataProviderBase.cs	Thu Mar 27 21:46:09 2014 +0400
@@ -0,0 +1,513 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Data.Common;
+using System.Data.Linq;
+using System.Linq;
+
+namespace BLToolkit.Data.DataProvider
+{
+	using Common;
+	using Mapping;
+	using Sql.SqlProvider;
+
+	/// <summary>
+	/// The <b>DataProviderBase</b> is a class that provides specific data provider information
+	/// for the <see cref="DbManager"/> class. 
+	/// </summary>
+	/// <remarks>
+	/// See the <see cref="DbManager.AddDataProvider(DataProviderBase)"/> method to find an example.
+	/// </remarks>
+	/// <seealso cref="DbManager.AddDataProvider(DataProviderBase)">AddDataManager Method</seealso>
+	public abstract partial class DataProviderBase : IMappingSchemaProvider
+	{
+		#region Abstract Properties
+
+		/// <summary>
+		/// Returns an actual type of the connection object used by this instance of the <see cref="DbManager"/>.
+		/// </summary>
+		/// <remarks>
+		/// See the <see cref="DbManager.AddDataProvider(DataProviderBase)"/> method to find an example.
+		/// </remarks>
+		/// <seealso cref="DbManager.AddDataProvider(DataProviderBase)">AddDataManager Method</seealso>
+		/// <value>An instance of the <see cref="Type"/> class.</value>
+		public abstract Type ConnectionType { get; }
+
+		/// <summary>
+		/// Returns the data manager name.
+		/// </summary>
+		/// <remarks>
+		/// See the <see cref="DbManager.AddDataProvider(DataProviderBase)"/> method to find an example.
+		/// </remarks>
+		/// <seealso cref="DbManager.AddDataProvider(DataProviderBase)">AddDataManager Method</seealso>
+		/// <value>The data manager name.</value>
+		public abstract string Name { get; }
+
+		private  string _uniqueName;
+		/// <summary>
+		/// Same as <see cref="Name"/>, but may be overridden to add two or more providers of same type.
+		/// </summary>
+		public string  UniqueName
+		{
+			get { return _uniqueName ?? Name; }
+			internal set { _uniqueName = value; }
+		}
+
+		#endregion
+
+		#region Abstract Methods
+
+		/// <summary>
+		/// Creates a new instance of the <see cref="IDbConnection"/>.
+		/// </summary>
+		/// <remarks>
+		/// See the <see cref="DbManager.AddDataProvider(DataProviderBase)"/> method to find an example.
+		/// </remarks>
+		/// <seealso cref="DbManager.AddDataProvider(DataProviderBase)">AddDataManager Method</seealso>
+		/// <returns>The <see cref="IDbConnection"/> object.</returns>
+		public abstract IDbConnection CreateConnectionObject();
+
+		/// <summary>
+		/// Creates a new connection object with same connection string.
+		/// </summary>
+		/// <param name="connection">A connection object used as prototype.</param>
+		/// <returns>New connection instance.</returns>
+		public virtual IDbConnection CloneConnection(IDbConnection connection)
+		{
+			if (connection == null)
+				throw new ArgumentNullException("connection");
+
+			var cloneable = connection as ICloneable;
+
+			if (cloneable != null)
+				return (IDbConnection)cloneable.Clone();
+
+			var newConnection = CreateConnectionObject();
+
+			// This is definitelly not enought when PersistSecurityInfo set to false.
+			//
+			newConnection.ConnectionString = connection.ConnectionString;
+
+			return newConnection;
+		}
+
+		/// <summary>
+		/// Creates an instance of the <see cref="DbDataAdapter"/>.
+		/// </summary>
+		/// <remarks>
+		/// See the <see cref="DbManager.AddDataProvider(DataProviderBase)"/> method to find an example.
+		/// </remarks>
+		/// <seealso cref="DbManager.AddDataProvider(DataProviderBase)">AddDataManager Method</seealso>
+		/// <returns>The <see cref="DbDataAdapter"/> object.</returns>
+		public abstract DbDataAdapter CreateDataAdapterObject();
+
+		/// <summary>
+		/// Populates the specified <see cref="IDbCommand"/> object's Parameters collection with 
+		/// parameter information for the stored procedure specified in the <see cref="IDbCommand"/>.
+		/// </summary>
+		/// <remarks>
+		/// See the <see cref="DbManager.AddDataProvider(DataProviderBase)"/> method to find an example.
+		/// </remarks>
+		/// <seealso cref="DbManager.AddDataProvider(DataProviderBase)">AddDataManager Method</seealso>
+		/// <param name="command">The <see cref="IDbCommand"/> referencing the stored procedure 
+		/// for which the parameter information is to be derived.
+		/// The derived parameters will be populated into the Parameters of this command.</param>
+		/// <returns>true - parameters can be derive.</returns>
+		public abstract bool DeriveParameters(IDbCommand command);
+
+		#endregion
+
+		#region Factory methods
+
+		public virtual IDbCommand CreateCommandObject(IDbConnection connection)
+		{
+			return connection.CreateCommand();
+		}
+
+		public virtual IDbDataParameter CreateParameterObject(IDbCommand command)
+		{
+			return command.CreateParameter();
+		}
+
+		#endregion
+
+		#region IDbDataParameter methods
+
+		public virtual IDbDataParameter GetParameter(
+			IDbCommand           command,
+			NameOrIndexParameter nameOrIndex)
+		{
+			return (IDbDataParameter)(nameOrIndex.ByName ?
+				command.Parameters[nameOrIndex.Name] : command.Parameters[nameOrIndex.Index]);
+		}
+
+		public virtual void AttachParameter(
+			IDbCommand       command,
+			IDbDataParameter parameter)
+		{
+			command.Parameters.Add(parameter);
+		}
+
+		public virtual void SetUserDefinedType(IDbDataParameter parameter, string typeName)
+		{
+			throw new NotSupportedException(Name + " data provider does not support UDT.");
+		}
+
+		public virtual bool IsValueParameter(IDbDataParameter parameter)
+		{
+			return parameter.Direction != ParameterDirection.ReturnValue;
+		}
+
+		public virtual IDbDataParameter CloneParameter(IDbDataParameter parameter)
+		{
+			return (IDbDataParameter)((ICloneable)parameter).Clone();
+		}
+
+		public virtual bool InitParameter(IDbDataParameter parameter)
+		{
+			return false;
+		}
+
+		#endregion
+
+		#region Virtual Members
+
+		/// <summary>
+		/// Open an <see cref="IDataReader"/> into the given RefCursor object
+		/// </summary>
+		/// <param name="refCursor">The refcursor to open an <see cref="IDataReader"/> to</param>
+		/// <returns>The <see cref="IDataReader"/> into the refcursor</returns>
+		public virtual IDataReader GetRefCursorDataReader(object refCursor)
+		{
+			throw new NotSupportedException("Operation not supported on this DataProvider");
+		}
+
+		public virtual object Convert(object value, ConvertType convertType)
+		{
+			return SqlProvider.Convert(value, convertType);
+		}
+
+		public virtual DataExceptionType ConvertErrorNumberToDataExceptionType(int number)
+		{
+			return DataExceptionType.Undefined;
+		}
+
+		public virtual void InitDbManager(DbManager dbManager)
+		{
+			var schema = MappingSchema;
+
+			if (schema != null)
+				dbManager.MappingSchema = schema;
+		}
+
+		/// <summary>
+		/// One time initialization from a configuration file.
+		/// </summary>
+		/// <param name="attributes">Provider specific attributes.</param>
+		public virtual void Configure(System.Collections.Specialized.NameValueCollection attributes)
+		{
+		}
+
+		public virtual MappingSchema MappingSchema { get; set; }
+
+		public virtual void PrepareCommand(ref CommandType commandType, ref string commandText, ref IDbDataParameter[] commandParameters)
+		{
+			/*
+			if (commandParameters != null) foreach (var p in commandParameters)
+			{
+				if (p.Value is System.Data.Linq.Binary)
+				{
+					var arr = ((System.Data.Linq.Binary)p.Value).ToArray();
+
+					p.Value  = arr;
+					p.DbType = DbType.Binary;
+					p.Size   = arr.Length;
+				}
+			}
+			*/
+		}
+
+		public virtual bool CanReuseCommand(IDbCommand command, CommandType newCommandType)
+		{
+			return true;
+		}
+
+		public virtual int ExecuteArray(IDbCommand command, int iterations)
+		{
+			// save parameter values
+			var parameters = command.Parameters
+				.OfType<IDbDataParameter>()
+				.Select(param => new
+				{
+					Parameter = param,
+					Value = param.Value as Array
+				})
+				.ToArray();
+
+			var outParameters = parameters
+				.Where(p =>
+					p.Parameter.Direction == ParameterDirection.InputOutput ||
+					p.Parameter.Direction == ParameterDirection.Output)
+				.ToArray();
+
+			// validate parameter values
+			foreach (var p in parameters)
+			{
+				if (p.Value == null)
+				{
+					throw new InvalidOperationException("ExecuteArray requires that all " +
+						"parameter values are arrays. Parameter name: " + p.Parameter.ParameterName);
+				}
+
+				if (p.Value.GetLength(0) != iterations)
+				{
+					throw new InvalidOperationException("ExecuteArray requires that array sizes are " +
+						"equal to the number of iterations. Parameter name: " + p.Parameter.ParameterName);
+				}
+			}
+
+			try
+			{
+				// run iterations
+				int rowsAffected = 0;
+				for (int iteration = 0; iteration < iterations; iteration++)
+				{
+					// copy input parameter values
+					foreach (var param in parameters)
+					{
+						SetParameterValue(param.Parameter, param.Value.GetValue(iteration));
+					}
+
+					rowsAffected += command.ExecuteNonQuery();
+
+					// return output parameter values
+					foreach (var param in outParameters)
+					{
+						var outputValue = param.Parameter.Value;
+						param.Value.SetValue(outputValue, iteration);
+					}
+				}
+
+				return rowsAffected;
+			}
+			finally
+			{
+				// restore parameter values
+				foreach (var param in parameters)
+				{
+					param.Parameter.Value = param.Value;
+				}
+			}
+		}
+
+        public virtual string GetSequenceQuery(string sequenceName)
+        {
+            return null;
+        }
+
+        public virtual string NextSequenceQuery(string sequenceName)
+        {
+            return null;
+        }
+
+        public virtual string GetReturningInto(string columnName)
+        {
+            return null;
+        }
+
+		public virtual void SetParameterValue(IDbDataParameter parameter, object value)
+		{
+			if (value is System.Data.Linq.Binary)
+			{
+				var arr = ((System.Data.Linq.Binary)value).ToArray();
+
+				parameter.Value  = arr;
+				parameter.DbType = DbType.Binary;
+				parameter.Size   = arr.Length;
+			}
+			else
+				parameter.Value = value;
+		}
+
+		public abstract ISqlProvider CreateSqlProvider();
+
+		private   ISqlProvider _sqlProvider;
+		protected ISqlProvider  SqlProvider
+		{
+			get { return _sqlProvider ?? (_sqlProvider = CreateSqlProvider()); }
+		}
+
+		public virtual IDataReader GetDataReader(MappingSchema schema, IDataReader dataReader)
+		{
+			return dataReader;
+		}
+
+        public virtual IDataReader GetDataReader(IDbCommand command, CommandBehavior commandBehavior)
+        {
+            return command.ExecuteReader(commandBehavior);
+        }
+
+		public virtual bool ParameterNamesEqual(string paramName1, string paramName2)
+		{
+			// default implementation is case-insensitive, because if we make it 
+			// case-sensitive and don't overload it in all existing providers - client code may break
+			return string.Equals(paramName1, paramName2, StringComparison.OrdinalIgnoreCase);
+		}
+
+		public virtual DbType GetDbType(Type systemType)
+		{
+			if (systemType == typeof(Binary) || systemType == typeof(byte[]))
+				return DbType.Binary;
+
+			return DbType.Object;
+		}
+
+		public virtual bool IsMarsEnabled(IDbConnection conn)
+		{
+			return false;
+		}
+
+		public virtual string ProviderName  { get { return ConnectionType.Namespace; } }
+		public virtual int    MaxParameters { get { return 100;   } }
+		public virtual int    MaxBatchSize  { get { return 65536; } }
+		public virtual string EndOfSql      { get { return ";";   } }
+
+		#endregion
+
+		#region DataReaderEx
+
+		protected class DataReaderBase<T> : IDataReader
+			where T: IDataReader
+		{
+			public readonly T DataReader;
+
+			protected DataReaderBase(T rd)
+			{
+				DataReader = rd;
+			}
+
+			#region Implementation of IDisposable
+
+			public void Dispose()
+			{
+				DataReader.Dispose();
+			}
+
+			#endregion
+
+			#region Implementation of IDataRecord
+
+			public string              GetName        (int i)           { return DataReader.GetName        (i); }
+			public string              GetDataTypeName(int i)           { return DataReader.GetDataTypeName(i); }
+			public Type                GetFieldType   (int i)           { return DataReader.GetFieldType   (i); }
+            // GetValue method is virtual since it can be overridden by some data provider 
+            // (For instance, OdbDataProvider uses special methodes for clob data fetching)
+			public virtual object      GetValue       (int i)           { return DataReader.GetValue       (i); }
+			public int                 GetValues      (object[] values) { return DataReader.GetValues      (values); }
+			public int                 GetOrdinal     (string   name)   { return DataReader.GetOrdinal     (name);   }
+			public bool                GetBoolean     (int i)           { return DataReader.GetBoolean     (i); }
+			public byte                GetByte        (int i)           { return DataReader.GetByte        (i); }
+			public char                GetChar        (int i)           { return DataReader.GetChar        (i); }
+			public Guid                GetGuid        (int i)           { return DataReader.GetGuid        (i); }
+			public short               GetInt16       (int i)           { return DataReader.GetInt16       (i); }
+			public int                 GetInt32       (int i)           { return DataReader.GetInt32       (i); }
+			public long                GetInt64       (int i)           { return DataReader.GetInt64       (i); }
+			public float               GetFloat       (int i)           { return DataReader.GetFloat       (i); }
+			public double              GetDouble      (int i)           { return DataReader.GetDouble      (i); }
+			public string              GetString      (int i)           { return DataReader.GetString      (i); }
+			public decimal             GetDecimal     (int i)           { return DataReader.GetDecimal     (i); }
+			public DateTime            GetDateTime    (int i)           { return DataReader.GetDateTime    (i); }
+			public IDataReader         GetData        (int i)           { return DataReader.GetData        (i); }
+			public bool                IsDBNull       (int i)           { return DataReader.IsDBNull       (i); }
+
+			public int FieldCount { get { return DataReader.FieldCount; } }
+
+			object IDataRecord.this[int i]       { get { return DataReader[i];    } }
+			object IDataRecord.this[string name] { get { return DataReader[name]; } }
+
+			public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
+			{
+				return DataReader.GetBytes(i, fieldOffset, buffer, bufferoffset, length);
+			}
+
+			public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
+			{
+				return DataReader.GetChars(i, fieldoffset, buffer, bufferoffset, length);
+			}
+
+			#endregion
+
+			#region Implementation of IDataReader
+
+			public void      Close         () {        DataReader.Close         (); }
+			public DataTable GetSchemaTable() { return DataReader.GetSchemaTable(); }
+			public bool      NextResult    () { return DataReader.NextResult    (); }
+			public bool      Read          () { return DataReader.Read          (); }
+			public int       Depth           { get { return DataReader.Depth;           } }
+			public bool      IsClosed        { get { return DataReader.IsClosed;        } }
+			public int       RecordsAffected { get { return DataReader.RecordsAffected; } }
+
+			#endregion
+		}
+
+		protected abstract class DataReaderEx<T> : DataReaderBase<T>, IDataReaderEx
+			where T: IDataReader
+		{
+			protected DataReaderEx(T rd) : base(rd)
+			{
+			}
+
+			#region Implementation of IDataReaderEx
+
+			public abstract DateTimeOffset GetDateTimeOffset(int i);
+
+			#endregion
+		}
+
+		#endregion
+
+		#region InsertBatch
+
+		public virtual int InsertBatchWithIdentity<T>(
+			DbManager db,
+			string insertText,
+			IEnumerable<T> collection,
+			MemberMapper[] members,
+			int maxBatchSize,
+			DbManager.ParameterProvider<T> getParameters)
+		{
+			throw new NotImplementedException("Insert batch with identity is not implemented!");
+		}
+
+		public virtual int InsertBatch<T>(
+			DbManager      db,
+			string         insertText,
+			IEnumerable<T> collection,
+			MemberMapper[] members,
+			int            maxBatchSize,
+			DbManager.ParameterProvider<T> getParameters)
+		{
+			db.SetCommand(insertText);
+			return db.ExecuteForEach(collection, members, maxBatchSize, getParameters);
+		}
+
+		#endregion
+
+		protected int ExecuteSqlList(DbManager db, IEnumerable<string> sqlList)
+		{
+			var cnt = 0;
+
+			foreach (string sql in sqlList)
+			{
+				cnt += db.SetCommand(sql).ExecuteNonQuery();
+			}
+
+			return cnt;
+		}
+
+		public virtual DbType GetParameterDbType(DbType dbType)
+		{
+			return dbType;
+		}
+	}
+}