Mercurial > pub > bltoolkit
view Source/Data/DataProvider/SqlDataProviderBase.cs @ 9:1e85f66cf767 default tip
update bltoolkit
author | nickolay |
---|---|
date | Thu, 05 Apr 2018 20:53:26 +0300 |
parents | f990fcb411a9 |
children |
line wrap: on
line source
using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Data.Common; using System.Data.SqlClient; using System.Linq; using SqlException = System.Data.SqlClient.SqlException; using SqlParameter = System.Data.SqlClient.SqlParameter; namespace BLToolkit.Data.DataProvider { using Mapping; using Sql.SqlProvider; /// <summary> /// Implements access to the Data Provider for SQL Server. /// </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 class SqlDataProviderBase : DataProviderBase { /// <summary> /// Creates the database connection object. /// </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 database connection object.</returns> public override IDbConnection CreateConnectionObject() { return new SqlConnection(); } /// <summary> /// Creates the data adapter object. /// </summary> /// <remarks> /// See the <see cref="DbManager.AddDataProvider(DataProviderBase)"/> method to find an example. /// </remarks> /// <seealso cref="DbManager.AddDataProvider(DataProviderBase)">AddDataManager Method</seealso> /// <returns>A data adapter object.</returns> public override DbDataAdapter CreateDataAdapterObject() { return new SqlDataAdapter(); } /// <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> public override bool DeriveParameters(IDbCommand command) { SqlCommandBuilder.DeriveParameters((SqlCommand)command); #if !MONO foreach (SqlParameter p in command.Parameters) { // We have to clear UDT type names. // Otherwise it will fail with error // "Database name is not allowed with a table-valued parameter" // but this is exactly the way how they are discovered. // if (p.SqlDbType == SqlDbType.Structured) { var firstDot = p.UdtTypeName.IndexOf('.'); if (firstDot >= 0) p.UdtTypeName = p.UdtTypeName.Substring(firstDot + 1); } } #endif return true; } public override void PrepareCommand(ref CommandType commandType, ref string commandText, ref IDbDataParameter[] commandParameters) { base.PrepareCommand(ref commandType, ref commandText, ref commandParameters); if (commandParameters == null) return; foreach (var p in commandParameters) { var val = p.Value; if (val == null || !val.GetType().IsArray || val is byte[] || val is char[]) continue; var dt = new DataTable(); dt.Columns.Add("column_value", val.GetType().GetElementType()); dt.BeginLoadData(); foreach (object o in (Array)val) { var row = dt.NewRow(); row[0] = o; dt.Rows.Add(row); } dt.EndLoadData(); p.Value = dt; } } public override void SetUserDefinedType(IDbDataParameter parameter, string typeName) { #if !MONO if (!(parameter is SqlParameter)) throw new ArgumentException("SqlParameter expected.", "parameter"); ((SqlParameter)parameter).UdtTypeName = typeName; #else throw new NotSupportedException(); #endif } public override object Convert(object value, ConvertType convertType) { switch (convertType) { case ConvertType.ExceptionToErrorNumber: if (value is SqlException) return ((SqlException)value).Number; break; } return SqlProvider.Convert(value, convertType); } public override DataExceptionType ConvertErrorNumberToDataExceptionType(int number) { switch (number) { case 1205: return DataExceptionType.Deadlock; case -2: return DataExceptionType.Timeout; case 547: return DataExceptionType.ForeignKeyViolation; case 2601: return DataExceptionType.UniqueIndexViolation; case 2627: return DataExceptionType.ConstraintViolation; } return DataExceptionType.Undefined; } /// <summary> /// Returns connection type. /// </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 override Type ConnectionType { get { return typeof(SqlConnection); } } public const string NameString = DataProvider.ProviderName.MsSql; /// <summary> /// Returns the data provider name. /// </summary> /// <remarks> /// See the <see cref="DbManager.AddDataProvider(DataProviderBase)"/> method to find an example. /// </remarks> /// <seealso cref="DbManager.AddDataProvider(DataProviderBase)">AddDataProvider Method</seealso> /// <value>Data provider name.</value> public override string Name { get { return NameString; } } public override ISqlProvider CreateSqlProvider() { return new MsSql2005SqlProvider(); } public override int MaxParameters { get { return 2100 - 20; } } public override int MaxBatchSize { get { return 65536; } } public override bool IsMarsEnabled(IDbConnection conn) { if (conn.ConnectionString != null) { return conn.ConnectionString.Split(';') .Select(s => s.Split('=')) .Where (s => s.Length == 2 && s[0].Trim().ToLower() == "multipleactiveresultsets") .Select(s => s[1].Trim().ToLower()) .Any (s => s == "true" || s == "1" || s == "yes"); } return false; } #region GetDataReader public override IDataReader GetDataReader(MappingSchema schema, IDataReader dataReader) { return dataReader is SqlDataReader? new SqlDataReaderEx((SqlDataReader)dataReader): base.GetDataReader(schema, dataReader); } class SqlDataReaderEx : DataReaderEx<SqlDataReader> { public SqlDataReaderEx(SqlDataReader rd): base(rd) { } public override DateTimeOffset GetDateTimeOffset(int i) { #if !MONO return DataReader.GetDateTimeOffset(i); #else throw new NotSupportedException(); #endif } } #endregion public override int InsertBatch<T>( DbManager db, string insertText, IEnumerable<T> collection, MemberMapper[] members, int maxBatchSize, DbManager.ParameterProvider<T> getParameters) { if (db.Transaction != null) return base.InsertBatch(db, insertText, collection, members, maxBatchSize, getParameters); var idx = insertText.IndexOf('\n'); var tbl = insertText.Substring(0, idx).Substring("INSERT INTO ".Length).TrimEnd('\r'); var rd = new BulkCopyReader(members, collection); var bc = new SqlBulkCopy((SqlConnection)db.Connection) { BatchSize = maxBatchSize, DestinationTableName = tbl, }; foreach (var memberMapper in members) bc.ColumnMappings.Add(new SqlBulkCopyColumnMapping(memberMapper.Ordinal, memberMapper.Name)); bc.WriteToServer(rd); return rd.Count; } class BulkCopyReader : IDataReader { readonly MemberMapper[] _members; readonly IEnumerable _collection; readonly IEnumerator _enumerator; public int Count; public BulkCopyReader(MemberMapper[] members, IEnumerable collection) { _members = members; _collection = collection; _enumerator = _collection.GetEnumerator(); } #region Implementation of IDisposable public void Dispose() { } #endregion #region Implementation of IDataRecord public string GetName(int i) { return _members[i].Name; } public Type GetFieldType(int i) { return _members[i].Type; } public object GetValue(int i) { return _members[i].GetValue(_enumerator.Current); } public int FieldCount { get { return _members.Length; } } public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length) { throw new NotImplementedException(); } public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length) { throw new NotImplementedException(); } public string GetDataTypeName(int i) { throw new NotImplementedException(); } public int GetValues (object[] values) { throw new NotImplementedException(); } public int GetOrdinal (string name) { throw new NotImplementedException(); } public bool GetBoolean (int i) { throw new NotImplementedException(); } public byte GetByte (int i) { throw new NotImplementedException(); } public char GetChar (int i) { throw new NotImplementedException(); } public Guid GetGuid (int i) { throw new NotImplementedException(); } public short GetInt16 (int i) { throw new NotImplementedException(); } public int GetInt32 (int i) { throw new NotImplementedException(); } public long GetInt64 (int i) { throw new NotImplementedException(); } public float GetFloat (int i) { throw new NotImplementedException(); } public double GetDouble (int i) { throw new NotImplementedException(); } public string GetString (int i) { throw new NotImplementedException(); } public decimal GetDecimal (int i) { throw new NotImplementedException(); } public DateTime GetDateTime (int i) { throw new NotImplementedException(); } public IDataReader GetData (int i) { throw new NotImplementedException(); } public bool IsDBNull (int i) { throw new NotImplementedException(); } object IDataRecord.this[int i] { get { throw new NotImplementedException(); } } object IDataRecord.this[string name] { get { throw new NotImplementedException(); } } #endregion #region Implementation of IDataReader public void Close() { throw new NotImplementedException(); } public DataTable GetSchemaTable() { throw new NotImplementedException(); } public bool NextResult() { throw new NotImplementedException(); } public bool Read() { var b = _enumerator.MoveNext(); if (b) Count++; return b; } public int Depth { get { throw new NotImplementedException(); } } public bool IsClosed { get { throw new NotImplementedException(); } } public int RecordsAffected { get { throw new NotImplementedException(); } } #endregion } public override void SetParameterValue(IDbDataParameter parameter, object value) { if (value is sbyte) { parameter.Value = (byte)(sbyte)value; } else if (value is ushort) { parameter.Value = (short)(ushort)value; } else if (value is uint) { parameter.Value = (int)(uint)value; } else if (value is ulong) { parameter.Value = (long)(ulong)value; } else if (value is string) { parameter.Value = value; if (parameter.DbType == DbType.String && ((string)value).Length == 0) parameter.Size = 1; } else { base.SetParameterValue(parameter, value); } } } }