/// <summary>Executes the batch delete operation.</summary> /// <typeparam name="T">The type of elements of the query.</typeparam> /// <param name="query">The query used to execute the batch operation.</param> /// <param name="updateFactory">The update factory.</param> /// <returns>The number of rows affected.</returns> public int Execute <T>(IQueryable <T> query, Expression <Func <T, T> > updateFactory) where T : class { // FIX query with visitor { var visitor = new BatchUpdateVisitor(); visitor.Visit(query.Expression); if (visitor.HasOrderBy) { query = query.Take(int.MaxValue); } } string expression = query.Expression.ToString(); if (Regex.IsMatch(expression, @"\.Where\(\w+ => False\)")) { return(0); } #if EF5 || EF6 var objectQuery = query.GetObjectQuery(); // GET model and info var model = query.GetDbContext().GetModel(); var entity = model.Entity <T>(); // TODO: Select only key + lambda columns // var keys = entity.Info.Key.PropertyRefs; //var queryKeys = query.SelectByName(keys.Select(x => x.Name).ToList()); //var innerObjectQuery = queryKeys.GetObjectQuery(); var innerObjectQuery = objectQuery; // GET UpdateSetValues var values = GetInnerValues(query, updateFactory, entity); // CREATE command var command = CreateCommand(innerObjectQuery, entity, values); // WHERE 1 = 0 if (command == null) { return(0); } // EXECUTE var ownConnection = false; try { if (innerObjectQuery.Context.Connection.State != ConnectionState.Open) { ownConnection = true; innerObjectQuery.Context.Connection.Open(); } if (Executing != null) { Executing(command); } var rowAffecteds = command.ExecuteNonQuery(); return(rowAffecteds); } finally { if (ownConnection && innerObjectQuery.Context.Connection.State != ConnectionState.Closed) { innerObjectQuery.Context.Connection.Close(); } } #elif EFCORE if (BatchUpdateManager.InMemoryDbContextFactory != null && query.IsInMemoryQueryContext()) { var context = BatchUpdateManager.InMemoryDbContextFactory(); var list = query.ToList(); var compiled = updateFactory.Compile(); var memberBindings = ((MemberInitExpression)updateFactory.Body).Bindings; var accessors = memberBindings .Select(x => x.Member.Name) .Select(x => new PropertyOrFieldAccessor(typeof(T).GetProperty(x, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))) .ToList(); foreach (var item in list) { var newItem = compiled(item); foreach (var accessor in accessors) { var value = accessor.GetValue(newItem); accessor.SetValue(item, value); } } context.SaveChanges(); return(list.Count); } var dbContext = query.GetDbContext(); var entity = dbContext.Model.FindEntityType(typeof(T)); // TODO: Select only key + lambda columns // var keys = entity.GetKeys().ToList()[0].Properties; //var queryKeys = query.SelectByName(keys.Select(x => x.Name).ToList()); //var innerObjectQuery = queryKeys.GetObjectQuery(); var queryKeys = query; // GET UpdateSetValues var values = GetInnerValues(query, updateFactory, entity); // CREATE command var command = CreateCommand(queryKeys, entity, values); // EXECUTE var ownConnection = false; try { if (dbContext.Database.GetDbConnection().State != ConnectionState.Open) { ownConnection = true; dbContext.Database.OpenConnection(); } if (Executing != null) { Executing(command); } var rowAffecteds = command.ExecuteNonQuery(); return(rowAffecteds); } finally { if (ownConnection && dbContext.Database.GetDbConnection().State != ConnectionState.Closed) { dbContext.Database.CloseConnection(); } } #endif }
/// <summary>Executes the batch delete operation.</summary> /// <typeparam name="T">The type of elements of the query.</typeparam> /// <param name="query">The query used to execute the batch operation.</param> /// <param name="updateFactory">The update factory.</param> /// <returns>The number of rows affected.</returns> public int Execute <T>(IQueryable <T> query, Expression <Func <T, T> > updateFactory) where T : class { // FIX query with visitor { var visitor = new BatchUpdateVisitor(); visitor.Visit(query.Expression); if (visitor.HasOrderBy) { query = query.Take(int.MaxValue); } } string expression = query.Expression.ToString(); if (Regex.IsMatch(expression, @"\.Where\(\w+ => False\)")) { return(0); } #if EF5 || EF6 var objectQuery = query.GetObjectQuery(); // GET model and info var model = query.GetDbContext().GetModel(); var entity = model.Entity <T>(); // TODO: Select only key + lambda columns // var keys = entity.Info.Key.PropertyRefs; //var queryKeys = query.SelectByName(keys.Select(x => x.Name).ToList()); //var innerObjectQuery = queryKeys.GetObjectQuery(); var innerObjectQuery = objectQuery; // GET UpdateSetValues var values = GetInnerValues(query, updateFactory, entity); // CREATE command var command = CreateCommand(innerObjectQuery, entity, values); // EXECUTE var ownConnection = false; try { if (innerObjectQuery.Context.Connection.State != ConnectionState.Open) { ownConnection = true; innerObjectQuery.Context.Connection.Open(); } if (Executing != null) { Executing(command); } var rowAffecteds = command.ExecuteNonQuery(); return(rowAffecteds); } finally { if (ownConnection && innerObjectQuery.Context.Connection.State != ConnectionState.Closed) { innerObjectQuery.Context.Connection.Close(); } } #elif EFCORE var dbContext = query.GetDbContext(); var entity = dbContext.Model.FindEntityType(typeof(T)); // TODO: Select only key + lambda columns // var keys = entity.GetKeys().ToList()[0].Properties; //var queryKeys = query.SelectByName(keys.Select(x => x.Name).ToList()); //var innerObjectQuery = queryKeys.GetObjectQuery(); var queryKeys = query; // GET UpdateSetValues var values = GetInnerValues(query, updateFactory, entity); // CREATE command var command = CreateCommand(queryKeys, entity, values); // EXECUTE var ownConnection = false; try { if (dbContext.Database.GetDbConnection().State != ConnectionState.Open) { ownConnection = true; dbContext.Database.OpenConnection(); } if (Executing != null) { Executing(command); } var rowAffecteds = command.ExecuteNonQuery(); return(rowAffecteds); } finally { if (ownConnection && dbContext.Database.GetDbConnection().State != ConnectionState.Closed) { dbContext.Database.CloseConnection(); } } #endif }