Exemplo n.º 1
0
        /// <summary />
        public static void Update <T>(this IQueryable <T> query, Expression <Func <T, T> > obj, QueryOptimizer optimizer, string connectionString)
            where T : Gravitybox.GeoLocation.EFDAL.IBusinessObject, new()
        {
            if (optimizer == null)
            {
                optimizer = new QueryOptimizer();
            }
            if (query == null)
            {
                throw new Exception("Query must be set");
            }

            //There is nothing to do
            if (query.ToString().Replace("\r", string.Empty).Split(new char[] { '\n' }).LastOrDefault().Trim() == "WHERE 1 = 0")
            {
                return;
            }

            var instanceKey = Guid.Empty;

            System.Data.Entity.Core.Objects.ObjectContext objectContext = null;
            try
            {
                var propContext = query.Provider.GetType().GetProperty("InternalContext");
                if (propContext != null)
                {
                    var context = propContext.GetValue(query.Provider);
                    if (context != null)
                    {
                        var oc = context.GetType().GetProperty("ObjectContext").GetValue(context) as System.Data.Entity.Core.Objects.ObjectContext;
                        objectContext = oc as System.Data.Entity.Core.Objects.ObjectContext;
                        instanceKey   = ((IContext)context.GetType().GetProperty("Owner").GetValue(context)).InstanceKey;
                        if (string.IsNullOrEmpty(connectionString))
                        {
                            var propCs = context.GetType().GetProperty("OriginalConnectionString");
                            if (propCs != null)
                            {
                                connectionString = (string)propCs.GetValue(context);
                            }
                        }
                    }
                }

                if (instanceKey == Guid.Empty)
                {
                    var context2 = query.Provider.GetType().GetField("_context", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
                    if (context2 != null)
                    {
                        var context = context2.GetValue(query.Provider);
                        objectContext = context as System.Data.Entity.Core.Objects.ObjectContext;
                        var qq = objectContext.InterceptionContext.DbContexts.First() as Gravitybox.GeoLocation.EFDAL.IGeoLocationEntities;
                        instanceKey = qq.InstanceKey;
                        if (string.IsNullOrEmpty(connectionString))
                        {
                            connectionString = Util.StripEFCS2Normal(objectContext.Connection.ConnectionString);
                        }
                    }
                }

                if (instanceKey == Guid.Empty)
                {
                    throw new Exception("Unknown context");
                }

                if (string.IsNullOrEmpty(connectionString))
                {
                    var propContext2 = query.GetType().GetProperty("Context");
                    if (propContext2 != null)
                    {
                        var context = propContext2.GetValue(query) as System.Data.Entity.Core.Objects.ObjectContext;
                        if (context != null)
                        {
                            var builder = new System.Data.Entity.Core.EntityClient.EntityConnectionStringBuilder(context.Connection.ConnectionString);
                            if (!string.IsNullOrWhiteSpace(builder.ProviderConnectionString))
                            {
                                objectContext    = context;
                                connectionString = builder.ProviderConnectionString;
                            }
                        }
                    }
                }
            }
            catch { }

            System.Data.Entity.Core.Objects.ObjectParameterCollection existingParams = null;
            {
                var objectQuery = query as System.Data.Entity.Core.Objects.ObjectQuery <T>;
                if (objectQuery == null)
                {
                    var internalQueryField = query.GetType().GetProperty("InternalQuery", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue(query);
                    if (internalQueryField != null)
                    {
                        objectQuery = internalQueryField.GetType().GetProperty("ObjectQuery").GetValue(internalQueryField) as System.Data.Entity.Core.Objects.ObjectQuery <T>;
                    }
                }

                if (objectQuery != null)
                {
                    var ss2 = objectQuery.ToTraceString();             //DO NOT REMOVE! must call this to init params
                    existingParams = objectQuery.GetType().GetProperty("Parameters").GetValue(objectQuery) as System.Data.Entity.Core.Objects.ObjectParameterCollection;
                }
            }

            var startTime   = DateTime.Now;
            var changedList = new Dictionary <string, object>();

            #region Parse Tree
            var propBody = obj.GetType().GetProperty("Body");
            if (propBody != null)
            {
                var body = propBody.GetValue(obj);
                if (body != null)
                {
                    var propBindings = body.GetType().GetProperty("Bindings");
                    if (propBindings != null)
                    {
                        var members = (IEnumerable <System.Linq.Expressions.MemberBinding>)propBindings.GetValue(body);
                        foreach (System.Linq.Expressions.MemberAssignment item in members)
                        {
                            var    name  = item.Member.Name;
                            object value = null;

                            if (item.Expression.Type == typeof(int?))
                            {
                                value = CompileValue <int?>(item.Expression);
                            }
                            else if (item.Expression.Type == typeof(int))
                            {
                                value = CompileValue <int>(item.Expression);
                            }

                            else if (item.Expression.Type == typeof(string))
                            {
                                value = CompileValue <string>(item.Expression);
                            }

                            else if (item.Expression.Type == typeof(bool?))
                            {
                                value = CompileValue <bool?>(item.Expression);
                            }
                            else if (item.Expression.Type == typeof(bool))
                            {
                                value = CompileValue <bool>(item.Expression);
                            }

                            else if (item.Expression.Type == typeof(byte?))
                            {
                                value = CompileValue <byte?>(item.Expression);
                            }
                            else if (item.Expression.Type == typeof(byte))
                            {
                                value = CompileValue <byte>(item.Expression);
                            }

                            else if (item.Expression.Type == typeof(char?))
                            {
                                value = CompileValue <char?>(item.Expression);
                            }
                            else if (item.Expression.Type == typeof(char))
                            {
                                value = CompileValue <char>(item.Expression);
                            }

                            else if (item.Expression.Type == typeof(decimal?))
                            {
                                value = CompileValue <decimal?>(item.Expression);
                            }
                            else if (item.Expression.Type == typeof(decimal))
                            {
                                value = CompileValue <decimal>(item.Expression);
                            }

                            else if (item.Expression.Type == typeof(double?))
                            {
                                value = CompileValue <double?>(item.Expression);
                            }
                            else if (item.Expression.Type == typeof(double))
                            {
                                value = CompileValue <double>(item.Expression);
                            }

                            else if (item.Expression.Type == typeof(float?))
                            {
                                value = CompileValue <float?>(item.Expression);
                            }
                            else if (item.Expression.Type == typeof(float))
                            {
                                value = CompileValue <float>(item.Expression);
                            }

                            else if (item.Expression.Type == typeof(long?))
                            {
                                value = CompileValue <long?>(item.Expression);
                            }
                            else if (item.Expression.Type == typeof(long))
                            {
                                value = CompileValue <long>(item.Expression);
                            }

                            else if (item.Expression.Type == typeof(short?))
                            {
                                value = CompileValue <short?>(item.Expression);
                            }
                            else if (item.Expression.Type == typeof(short))
                            {
                                value = CompileValue <short>(item.Expression);
                            }

                            else if (item.Expression.Type == typeof(DateTime?))
                            {
                                value = CompileValue <DateTime?>(item.Expression);
                            }
                            else if (item.Expression.Type == typeof(DateTime))
                            {
                                value = CompileValue <DateTime>(item.Expression);
                            }

                            else if (item.Expression.Type == typeof(Guid?))
                            {
                                value = CompileValue <Guid?>(item.Expression);
                            }
                            else if (item.Expression.Type == typeof(Guid))
                            {
                                value = CompileValue <Guid>(item.Expression);
                            }

                            else
                            {
                                throw new Exception("Data type is not handled '" + item.Expression.Type.Name + "'");
                            }

                            changedList.Add(name, value);
                        }
                    }
                    else
                    {
                        throw new Exception("Update statement must be in format 'm => new Entity { Field = 0 }'");
                    }
                }
            }
            #endregion

            //Create a mapping for inheritance
            var mapping = new List <UpdateSqlMapItem>();
            IReadOnlyBusinessObject theObj = new T();
            do
            {
                var md = theObj.GetMetaData();
                mapping.Add(new UpdateSqlMapItem {
                    TableName = md.GetTableName(), FieldList = md.GetFields(), Schema = md.Schema(), Metadata = md
                });
                var newT = md.InheritsFrom();
                if (newT == null)
                {
                    theObj = default(T);
                }
                else
                {
                    theObj = (IReadOnlyBusinessObject)Activator.CreateInstance(newT, false);
                }
            } while (theObj != null);

            var paramIndex = 0;
            var parameters = new List <System.Data.SqlClient.SqlParameter>();
            foreach (var key in changedList.Keys)
            {
                var map      = mapping.First(x => x.FieldList.Any(z => z == key));
                var fieldSql = map.SqlList;
                var value    = changedList[key];
                if (value == null)
                {
                    fieldSql.Add("[" + map.Metadata.GetDatabaseFieldName(key) + "] = NULL");
                }
                else if (value is string)
                {
                    fieldSql.Add("[" + map.Metadata.GetDatabaseFieldName(key) + "] = @param" + paramIndex);
                    parameters.Add(new System.Data.SqlClient.SqlParameter {
                        ParameterName = "@param" + paramIndex, DbType = System.Data.DbType.String, Value = changedList[key]
                    });
                }
                else if (value is DateTime)
                {
                    fieldSql.Add("[" + map.Metadata.GetDatabaseFieldName(key) + "] = @param" + paramIndex);
                    parameters.Add(new System.Data.SqlClient.SqlParameter {
                        ParameterName = "@param" + paramIndex, DbType = System.Data.DbType.DateTime, Value = changedList[key]
                    });
                }
                else
                {
                    fieldSql.Add("[" + map.Metadata.GetDatabaseFieldName(key) + "] = @param" + paramIndex);
                    parameters.Add(new System.Data.SqlClient.SqlParameter {
                        ParameterName = "@param" + paramIndex, Value = changedList[key]
                    });
                }
                paramIndex++;
            }

            var sb = new System.Text.StringBuilder();
            #region Per table code
            if (typeof(T) == typeof(Gravitybox.GeoLocation.EFDAL.Entity.CanadaPostalCode))
            {
                sb.AppendLine("set rowcount " + optimizer.ChunkSize + ";");
                foreach (var item in mapping.Where(x => x.SqlList.Any()).ToList())
                {
                    sb.AppendLine("UPDATE [X] SET");
                    sb.AppendLine(string.Join(", ", item.SqlList));
                    sb.AppendLine("FROM [" + item.Schema + "].[" + item.TableName + "] AS [X] INNER JOIN (");
                    sb.AppendLine(((IQueryable <Gravitybox.GeoLocation.EFDAL.Entity.CanadaPostalCode>)query).Select(x => new { x.RowId }).ToString());
                    sb.AppendLine(") AS [Extent2]");
                    sb.AppendLine("on [X].[RowId] = [Extent2].[RowId]");
                    sb.AppendLine("select @@ROWCOUNT");
                }
            }
            else if (typeof(T) == typeof(Gravitybox.GeoLocation.EFDAL.Entity.City))
            {
                sb.AppendLine("set rowcount " + optimizer.ChunkSize + ";");
                foreach (var item in mapping.Where(x => x.SqlList.Any()).ToList())
                {
                    sb.AppendLine("UPDATE [X] SET");
                    sb.AppendLine(string.Join(", ", item.SqlList));
                    sb.AppendLine("FROM [" + item.Schema + "].[" + item.TableName + "] AS [X] INNER JOIN (");
                    sb.AppendLine(((IQueryable <Gravitybox.GeoLocation.EFDAL.Entity.City>)query).Select(x => new { x.CityId }).ToString());
                    sb.AppendLine(") AS [Extent2]");
                    sb.AppendLine("on [X].[CityId] = [Extent2].[CityId]");
                    sb.AppendLine("select @@ROWCOUNT");
                }
            }
            else if (typeof(T) == typeof(Gravitybox.GeoLocation.EFDAL.Entity.State))
            {
                sb.AppendLine("set rowcount " + optimizer.ChunkSize + ";");
                foreach (var item in mapping.Where(x => x.SqlList.Any()).ToList())
                {
                    sb.AppendLine("UPDATE [X] SET");
                    sb.AppendLine(string.Join(", ", item.SqlList));
                    sb.AppendLine("FROM [" + item.Schema + "].[" + item.TableName + "] AS [X] INNER JOIN (");
                    sb.AppendLine(((IQueryable <Gravitybox.GeoLocation.EFDAL.Entity.State>)query).Select(x => new { x.StateId }).ToString());
                    sb.AppendLine(") AS [Extent2]");
                    sb.AppendLine("on [X].[StateId] = [Extent2].[StateId]");
                    sb.AppendLine("select @@ROWCOUNT");
                }
            }
            else if (typeof(T) == typeof(Gravitybox.GeoLocation.EFDAL.Entity.Zip))
            {
                sb.AppendLine("set rowcount " + optimizer.ChunkSize + ";");
                foreach (var item in mapping.Where(x => x.SqlList.Any()).ToList())
                {
                    sb.AppendLine("UPDATE [X] SET");
                    sb.AppendLine(string.Join(", ", item.SqlList));
                    sb.AppendLine("FROM [" + item.Schema + "].[" + item.TableName + "] AS [X] INNER JOIN (");
                    sb.AppendLine(((IQueryable <Gravitybox.GeoLocation.EFDAL.Entity.Zip>)query).Select(x => new { x.ZipId }).ToString());
                    sb.AppendLine(") AS [Extent2]");
                    sb.AppendLine("on [X].[ZipId] = [Extent2].[ZipId]");
                    sb.AppendLine("select @@ROWCOUNT");
                }
            }
            else
            {
                throw new Exception("Entity type not found");
            }
            #endregion

            if (string.IsNullOrEmpty(connectionString))
            {
                connectionString = GeoLocationEntities.GetConnectionString();
            }

            var newParams = new List <System.Data.SqlClient.SqlParameter>();
            if (existingParams != null)
            {
                foreach (var ep in existingParams)
                {
                    newParams.Add(new System.Data.SqlClient.SqlParameter {
                        ParameterName = ep.Name, Value = (ep.Value == null ? System.DBNull.Value : ep.Value)
                    });
                }
            }
            newParams.AddRange(parameters);
            QueryPreCache.AddUpdate(instanceKey, sb.ToString(), newParams, optimizer);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Delete all records that match a where condition
        /// </summary>
        public static void  Delete <T>(this IQueryable <T> query, QueryOptimizer optimizer, string connectionString)
            where T : Gravitybox.GeoLocation.EFDAL.IBusinessObject, new()
        {
            if (optimizer == null)
            {
                optimizer = new QueryOptimizer();
            }
            if (query == null)
            {
                throw new Exception("Query must be set");
            }

            //There is nothing to do
            if (query.ToString().Replace("\r", string.Empty).Split(new char[] { '\n' }).LastOrDefault().Trim() == "WHERE 1 = 0")
            {
                return;
            }

            var instanceKey = Guid.Empty;

            System.Data.Entity.Core.Objects.ObjectContext objectContext = null;
            try
            {
                var propContext = query.Provider.GetType().GetProperty("InternalContext");
                if (propContext != null)
                {
                    var context = propContext.GetValue(query.Provider);
                    if (context != null)
                    {
                        var oc = context.GetType().GetProperty("ObjectContext").GetValue(context) as System.Data.Entity.Core.Objects.ObjectContext;
                        objectContext = oc as System.Data.Entity.Core.Objects.ObjectContext;
                        instanceKey   = ((IContext)context.GetType().GetProperty("Owner").GetValue(context)).InstanceKey;
                        if (string.IsNullOrEmpty(connectionString))
                        {
                            var propCs = context.GetType().GetProperty("OriginalConnectionString");
                            if (propCs != null)
                            {
                                connectionString = (string)propCs.GetValue(context);
                            }
                        }
                    }
                }

                if (instanceKey == Guid.Empty)
                {
                    var context2 = query.Provider.GetType().GetField("_context", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
                    if (context2 != null)
                    {
                        var context = context2.GetValue(query.Provider);
                        objectContext = context as System.Data.Entity.Core.Objects.ObjectContext;
                        var qq = objectContext.InterceptionContext.DbContexts.First() as Gravitybox.GeoLocation.EFDAL.IGeoLocationEntities;
                        if (qq != null)
                        {
                            instanceKey = qq.InstanceKey;
                        }
                        if (string.IsNullOrEmpty(connectionString))
                        {
                            connectionString = Util.StripEFCS2Normal(objectContext.Connection.ConnectionString);
                        }
                    }
                }

                if (instanceKey == Guid.Empty)
                {
                    throw new Exception("Unknown context");
                }

                if (string.IsNullOrEmpty(connectionString))
                {
                    var propContext2 = query.GetType().GetProperty("Context");
                    if (propContext2 != null)
                    {
                        var context = propContext2.GetValue(query) as System.Data.Entity.Core.Objects.ObjectContext;
                        if (context != null)
                        {
                            var builder = new System.Data.Entity.Core.EntityClient.EntityConnectionStringBuilder(context.Connection.ConnectionString);
                            if (!string.IsNullOrWhiteSpace(builder.ProviderConnectionString))
                            {
                                objectContext    = context;
                                connectionString = builder.ProviderConnectionString;
                            }
                        }
                    }
                }
            }
            catch { }

            System.Data.Entity.Core.Objects.ObjectParameterCollection existingParams = null;
            {
                var objectQuery = query as System.Data.Entity.Core.Objects.ObjectQuery <T>;
                if (objectQuery == null)
                {
                    var internalQueryField = query.GetType().GetProperty("InternalQuery", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue(query);
                    if (internalQueryField != null)
                    {
                        objectQuery = internalQueryField.GetType().GetProperty("ObjectQuery").GetValue(internalQueryField) as System.Data.Entity.Core.Objects.ObjectQuery <T>;
                    }
                }

                if (objectQuery != null)
                {
                    var ss2 = objectQuery.ToTraceString();             //DO NOT REMOVE! must call this to init params
                    existingParams = objectQuery.GetType().GetProperty("Parameters").GetValue(objectQuery) as System.Data.Entity.Core.Objects.ObjectParameterCollection;
                }
            }

            var sb = new System.Text.StringBuilder();

            #region Per table code
            if (typeof(T) == typeof(Gravitybox.GeoLocation.EFDAL.Entity.CanadaPostalCode))
            {
                sb.AppendLine("set rowcount " + optimizer.ChunkSize + ";");
                sb.AppendLine("delete [X] from [dbo].[CanadaPostalCode] [X] inner join (");
                sb.AppendLine(((IQueryable <Gravitybox.GeoLocation.EFDAL.Entity.CanadaPostalCode>)query).Select(x => new { x.RowId }).ToString());
                sb.AppendLine(") AS [Extent2]");
                sb.AppendLine("on [X].[RowId] = [Extent2].[RowId]");
                sb.AppendLine("select @@ROWCOUNT");
            }
            else if (typeof(T) == typeof(Gravitybox.GeoLocation.EFDAL.Entity.City))
            {
                sb.AppendLine("set rowcount " + optimizer.ChunkSize + ";");
                sb.AppendLine("delete [X] from [dbo].[City] [X] inner join (");
                sb.AppendLine(((IQueryable <Gravitybox.GeoLocation.EFDAL.Entity.City>)query).Select(x => new { x.CityId }).ToString());
                sb.AppendLine(") AS [Extent2]");
                sb.AppendLine("on [X].[CityId] = [Extent2].[CityId]");
                sb.AppendLine("select @@ROWCOUNT");
            }
            else if (typeof(T) == typeof(Gravitybox.GeoLocation.EFDAL.Entity.State))
            {
                sb.AppendLine("set rowcount " + optimizer.ChunkSize + ";");
                sb.AppendLine("delete [X] from [dbo].[State] [X] inner join (");
                sb.AppendLine(((IQueryable <Gravitybox.GeoLocation.EFDAL.Entity.State>)query).Select(x => new { x.StateId }).ToString());
                sb.AppendLine(") AS [Extent2]");
                sb.AppendLine("on [X].[StateId] = [Extent2].[StateId]");
                sb.AppendLine("select @@ROWCOUNT");
            }
            else if (typeof(T) == typeof(Gravitybox.GeoLocation.EFDAL.Entity.Zip))
            {
                sb.AppendLine("set rowcount " + optimizer.ChunkSize + ";");
                sb.AppendLine("delete [X] from [dbo].[Zip] [X] inner join (");
                sb.AppendLine(((IQueryable <Gravitybox.GeoLocation.EFDAL.Entity.Zip>)query).Select(x => new { x.ZipId }).ToString());
                sb.AppendLine(") AS [Extent2]");
                sb.AppendLine("on [X].[ZipId] = [Extent2].[ZipId]");
                sb.AppendLine("select @@ROWCOUNT");
            }
            else
            {
                throw new Exception("Entity type not found");
            }
            #endregion
            if (string.IsNullOrEmpty(connectionString))
            {
                connectionString = GeoLocationEntities.GetConnectionString();
            }

            var newParams = new List <System.Data.SqlClient.SqlParameter>();
            if (existingParams != null)
            {
                foreach (var ep in existingParams)
                {
                    newParams.Add(new System.Data.SqlClient.SqlParameter {
                        ParameterName = ep.Name, Value = (ep.Value == null ? System.DBNull.Value : ep.Value)
                    });
                }
            }
            QueryPreCache.AddDelete(instanceKey, sb.ToString(), newParams, optimizer);
        }