linq to sql batch delete

后端 未结 4 1144
一生所求
一生所求 2021-01-13 01:06

I have the following DB: Posts which have an Id, Tags also with Id, and TagsToPosts table which have T

相关标签:
4条回答
  • 2021-01-13 01:40

    You can't do this with LINQ-to-SQL.

    LINQ-to-SQL is not good for batch operations - it can't do batch inserts, it can't do batch updates, and it can't do batch deletes. Every object in your collection is treated individually. You can do all the operations in one transaction, but there will always be a query for each record.

    MSDN

    A better option is to write a stored procedure that will do what you want.

    0 讨论(0)
  • 2021-01-13 01:40

    PLINQO supports batch delete operations without retrieving the entities first.

    var delete = from t in TagsToPost select t).Except(from nt in newList select nt, new TagComparer())

    context.Tags.Delete(delete);

    http://plinqo.com

    0 讨论(0)
  • 2021-01-13 01:42

    Have you looked at the Linq Except operator?

    For example:

    var toDelete = (from t in TagsToPost
                    select t).Except(from nt in newList
                                     select nt, new TagComparer());
    
    class TagComparer: IEqualityComparer<TagsToPosts>
    {
        public bool Equals(TagsToPosts x, TagsToPosts y)
        {
             return x.Tag.Equals(y.Tag, CompareOptions.Ordinal);
        }
    }
    
    0 讨论(0)
  • 2021-01-13 01:50

    My solution which lets you make deletions determined by a class field:

    public static void DeleteByPropertyList<T, R>(List<T> listToDelete, Expression<Func<T, R>> getField, DataContext context) where T : class {
        List<List<string>> partitionedDeletes = listToDelete.Select(d => string.Format("'{0}'", getField.Compile()(d).ToString())).ToList().Partition<string>(2000).ToList();
        Func<Expression<Func<T, R>>, string> GetFieldName = propertyLambda => ((MemberExpression)propertyLambda.Body).Member.Name;
        MetaTable metaTable = context.Mapping.GetTable(typeof(T));
        string tableName = string.Format("{0}.{1}", metaTable.Model.DatabaseName, metaTable.TableName);
        foreach (List<string> partitionDelete in partitionedDeletes) {
            string statement = "delete from {0} where {1} in ({2})";
            statement = string.Format(statement, tableName, GetFieldName(getField), string.Join(",", partitionDelete));
            context.ExecuteCommand(statement);
        }
    }
    
    public static IEnumerable<List<T>> Partition<T>(this IList<T> source, int size) {
        for (int i = 0; i < Math.Ceiling(source.Count / (double)size); i++)
        yield return new List<T>(source.Skip(size * i).Take(size));
    }
    

    Usage:

        List<OrderItem> deletions = new List<OrderItem>();
        // populate deletions
        LinqToSqlHelper.DeleteByPropertyList<OrderItem, long>(deletions, oi => oi.OrderItemId, context);
    

    It only works with a single field, but it could be extended to composite fields easily enough.

    0 讨论(0)
提交回复
热议问题