Mercurial > pub > bltoolkit
diff Source/Data/DbManager.Linq.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/DbManager.Linq.cs Thu Mar 27 21:46:09 2014 +0400 @@ -0,0 +1,366 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Reflection; +using System.Text; + +using BLToolkit.Aspects; + +namespace BLToolkit.Data +{ + using DataProvider; + using Linq; + using Sql; + using Sql.SqlProvider; + + public partial class DbManager : IDataContext + { + public Table<T> GetTable<T>() + where T : class + { + return new Table<T>(this); + } + + public Table<T> GetTable<T>(bool dispose) + where T : class + { + return new Table<T>(new DataContextInfo(this, dispose)); + } + + public Table<T> GetTable<T>(object instance, [NotNull]MethodInfo methodInfo, [NotNull] params object[] parameters) + where T : class + { + return Linq.Extensions.GetTable<T>(this, instance, methodInfo, parameters); + } + + class PreparedQuery + { + public string[] Commands; + public List<SqlParameter> SqlParameters; + public IDbDataParameter[] Parameters; + public SqlQuery SqlQuery; + public ISqlProvider SqlProvider; + } + + #region SetQuery + + object IDataContext.SetQuery(IQueryContext queryContext) + { + var query = GetCommand(queryContext); + + GetParameters(queryContext, query); + + if (TraceSwitch.TraceInfo) + WriteTraceLine(((IDataContext)this).GetSqlText(query).Replace("\r", ""), TraceSwitch.DisplayName); + + return query; + } + + PreparedQuery GetCommand(IQueryContext query) + { + if (query.Context != null) + { + return new PreparedQuery + { + Commands = (string[])query.Context, + SqlParameters = query.SqlQuery.Parameters, + SqlQuery = query.SqlQuery + }; + } + + var sql = query.SqlQuery.ProcessParameters(); + + var newSql = ProcessQuery(sql); + + if (sql != newSql) + { + sql = newSql; + sql.IsParameterDependent = true; + } + + var sqlProvider = DataProvider.CreateSqlProvider(); + + var cc = sqlProvider.CommandCount(sql); + var sb = new StringBuilder(); + + var commands = new string[cc]; + + for (var i = 0; i < cc; i++) + { + sb.Length = 0; + + sqlProvider.BuildSql(i, sql, sb, 0, 0, false); + commands[i] = sb.ToString(); + } + + if (!query.SqlQuery.IsParameterDependent) + query.Context = commands; + + return new PreparedQuery + { + Commands = commands, + SqlParameters = sql.Parameters, + SqlQuery = sql, + SqlProvider = sqlProvider + }; + } + + protected virtual SqlQuery ProcessQuery(SqlQuery sqlQuery) + { + return sqlQuery; + } + + void GetParameters(IQueryContext query, PreparedQuery pq) + { + var parameters = query.GetParameters(); + + if (parameters.Length == 0 && pq.SqlParameters.Count == 0) + return; + + var x = DataProvider.Convert("x", ConvertType.NameToQueryParameter).ToString(); + var y = DataProvider.Convert("y", ConvertType.NameToQueryParameter).ToString(); + + var parms = new List<IDbDataParameter>(x == y ? pq.SqlParameters.Count : parameters.Length); + + if (x == y) + { + for (var i = 0; i < pq.SqlParameters.Count; i++) + { + var sqlp = pq.SqlParameters[i]; + + if (sqlp.IsQueryParameter) + { + var parm = parameters.Length > i && parameters[i] == sqlp ? parameters[i] : parameters.First(p => p == sqlp); + AddParameter(parms, x, parm); + } + } + } + else + { + foreach (var parm in parameters) + { + if (parm.IsQueryParameter && pq.SqlParameters.Contains(parm)) + { + var name = DataProvider.Convert(parm.Name, ConvertType.NameToQueryParameter).ToString(); + AddParameter(parms, name, parm); + } + } + } + + pq.Parameters = parms.ToArray(); + } + + void AddParameter(ICollection<IDbDataParameter> parms, string name, SqlParameter parm) + { + var value = MappingSchema.ConvertParameterValue(parm.Value, parm.SystemType); + + if (value != null) + { + if (parm.DbType == DbType.Object) + parms.Add(Parameter(name, value)); + else if (parm.DbSize == 0) + parms.Add(Parameter(name, value, parm.DbType)); + else + parms.Add(Parameter(name, value, parm.DbType, parm.DbSize)); + } + else + { + var dataType = DataProvider.GetDbType(parm.SystemType); + if (parm.DbType != DbType.Object) + dataType = parm.DbType; + parms.Add(dataType == DbType.Object ? Parameter(name, value) : Parameter(name, null, dataType)); + } + } + + #endregion + + #region ExecuteXXX + + int IDataContext.ExecuteNonQuery(object query) + { + var pq = (PreparedQuery)query; + + SetCommand(pq.Commands[0], pq.Parameters); + + var now = default(DateTime); + + if (TraceSwitch.TraceInfo) + now = DateTime.Now; + + var n = ExecuteNonQuery(); + + if (TraceSwitch.TraceInfo) + WriteTraceLine(string.Format("Execution time: {0}. Records affected: {1}.\r\n", DateTime.Now - now, n), TraceSwitch.DisplayName); + + return n; + } + + object IDataContext.ExecuteScalar(object query) + { + var now = default(DateTime); + + if (TraceSwitch.TraceInfo) + now = DateTime.Now; + + var ret = ExecuteScalarInternal(query); + + if (TraceSwitch.TraceInfo) + WriteTraceLine(string.Format("Execution time: {0}\r\n", DateTime.Now - now), TraceSwitch.DisplayName); + + return ret; + } + + object ExecuteScalarInternal(object query) + { + var pq = (PreparedQuery)query; + + SetCommand(pq.Commands[0], pq.Parameters); + + IDbDataParameter idparam = null; + + if ((pq.SqlProvider ?? DataProvider.CreateSqlProvider()).IsIdentityParameterRequired) + { + var sql = pq.SqlQuery; + + if (sql.IsInsert && sql.Insert.WithIdentity) + { + var pname = DataProvider.Convert("IDENTITY_PARAMETER", ConvertType.NameToQueryParameter).ToString(); + idparam = OutputParameter(pname, DbType.Decimal); + DataProvider.AttachParameter(Command, idparam); + } + } + + if (pq.Commands.Length == 1) + { + if (idparam != null) + { + ExecuteNonQuery(); // так сделано потому, что фаерберд провайдер не возвращает никаких параметров через ExecuteReader + // остальные провайдеры должны поддерживать такой режим + return idparam.Value; + } + + return ExecuteScalar(); + } + + ExecuteNonQuery(); + + return SetCommand(pq.Commands[1]).ExecuteScalar(); + } + + IDataReader IDataContext.ExecuteReader(object query) + { + var pq = (PreparedQuery)query; + + SetCommand(pq.Commands[0], pq.Parameters); + + var now = default(DateTime); + + if (TraceSwitch.TraceInfo) + now = DateTime.Now; + + var ret = ExecuteReader(); + + if (TraceSwitch.TraceInfo) + WriteTraceLine(string.Format("Execution time: {0}\r\n", DateTime.Now - now), TraceSwitch.DisplayName); + + return ret; + } + + void IDataContext.ReleaseQuery(object query) + { + } + + #endregion + + #region GetSqlText + + string IDataContext.GetSqlText(object query) + { + var pq = (PreparedQuery)query; + + var sqlProvider = pq.SqlProvider ?? DataProvider.CreateSqlProvider(); + + var sb = new StringBuilder(); + + sb.Append("-- ").Append(ConfigurationString); + + if (ConfigurationString != DataProvider.Name) + sb.Append(' ').Append(DataProvider.Name); + + if (DataProvider.Name != sqlProvider.Name) + sb.Append(' ').Append(sqlProvider.Name); + + sb.AppendLine(); + + if (pq.Parameters != null && pq.Parameters.Length > 0) + { + foreach (var p in pq.Parameters) + sb + .Append("-- DECLARE ") + .Append(p.ParameterName) + .Append(' ') + .Append(p.Value == null ? p.DbType.ToString() : p.Value.GetType().Name) + .AppendLine(); + + sb.AppendLine(); + + foreach (var p in pq.Parameters) + { + var value = p.Value; + + if (value is string || value is char) + value = "'" + value.ToString().Replace("'", "''") + "'"; + + sb + .Append("-- SET ") + .Append(p.ParameterName) + .Append(" = ") + .Append(value) + .AppendLine(); + } + + sb.AppendLine(); + } + + foreach (var command in pq.Commands) + sb.AppendLine(command); + + while (sb[sb.Length - 1] == '\n' || sb[sb.Length - 1] == '\r') + sb.Length--; + + sb.AppendLine(); + + return sb.ToString(); + } + + #endregion + + #region IDataContext Members + + IDataContext IDataContext.Clone(bool forNestedQuery) + { + if (forNestedQuery && _connection != null && IsMarsEnabled) + return new DbManager(_dataProvider, _connection) { _mappingSchema = _mappingSchema, _transaction = _transaction }; + + return Clone(); + } + + string IDataContext.ContextID + { + get { return DataProvider.Name; } + } + + static Func<ISqlProvider> GetCreateSqlProvider(DataProviderBase dp) + { + return dp.CreateSqlProvider; + } + + Func<ISqlProvider> IDataContext.CreateSqlProvider + { + get { return GetCreateSqlProvider(DataProvider); } + } + + #endregion + } +}