LINQ to SQL 批量删除

5
我有以下数据库: Posts,它们具有IdTags也具有Id,并且TagsToPosts表具有TagsToPosts.PostId => Posts.IdTagsToPosts.TagId => Tags.Id的FK关系。 我需要以以下方式从TagsToPosts中删除多个项目。 我通过解析一个字符串来创建IList<Tag> newTags。每个标记都有其名称。我想删除所有指向单个帖子的TagsToPosts项目(TagsToPosts.PostId == mypostid),并且指向不在我的newTags中的标记的项目。
例如,我有一个带有Id = 1的帖子,三个标签:1 => "tag1",2 => "tag2",3 => "tag3"和许多对多关系表TagsToPosts1 => 1,1 => 2,1 => 3 所以所有三个标记都链接到我的帖子。 之后,我将通过解析字符串创建一个新的IList<Tag> newList = new List<Tag>()newList包含:0 => "tag1",0 => "tag2"。 现在,我想从表TagsToPosts中删除第三个关系,因为我的新标记列表不包含名称为“tag3”的标记。所以我需要找到一个差异。我知道我可以使用JOIN查找相似的项目,但如何查找差异呢?
我希望这可以在一个数据库查询中完成,而不是迭代每个要删除的项目。
4个回答

3

使用LINQ-to-SQL无法完成此操作。

LINQ-to-SQL不适用于批量操作-它无法进行批量插入、批量更新和批量删除。您集合中的每个对象都会单独处理。您可以在一个事务中执行所有操作,但每条记录仍将进行一次查询。

MSDN

更好的选择是编写一个存储过程来完成您想要的操作。


0

我的解决方案允许您根据类字段进行删除操作:

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));
}

使用方法:

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

它只能与单个字段一起使用,但可以很容易地扩展到复合字段。


0
你看过Linq Except运算符吗?
例如:
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

PLINQO支持批量删除操作,无需先检索实体。

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

context.Tags.Delete(delete);

http://plinqo.com


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接