2009-03-17 40 views
5

Tôi có DB sau: Posts có một Id, Tags cũng với Id, và TagsToPosts bảng có TagsToPosts.PostId => Posts.IdTagsToPosts.TagId => Tags.Id quan hệ FK. Tôi cần xóa nhiều mục từ TagsToPosts theo cách sau. Tôi đang tạo IList<Tag> newTags bằng cách phân tích chuỗi. Mỗi thẻ có tên của nó. Tôi muốn xóa tất cả các mục TagsToPosts trỏ đến một bài đăng (TagsToPosts.PostId == mypostid) và trỏ tới Tag có tên không nằm trong số newTags của tôi.LINQ to batch sql xóa

Ví dụ tôi có một bài với Id = 1, ba thẻ: 1 => "tag1", 2 => "tag2", 3 => "tag3" Và ManyToMany quan hệ bảng TagsToPosts: 1 => 1, 1 => 2, 1 => 3 Vì vậy, tất cả ba thẻ được liên kết đến bài viết của tôi. Sau đó tôi sẽ tạo một IList<Tag> newList = new List<Tag>() mới bằng cách phân tích chuỗi. newList chứa: 0 => "tag1", 0 => "tag2". Bây giờ tôi muốn loại bỏ mối quan hệ thứ ba khỏi bảng TagsToPosts vì danh sách thẻ mới của tôi không chứa thẻ có tên "tag3". Vì vậy, tôi cần phải tìm một sự khác biệt. Tôi biết tôi có thể tìm thấy các mặt hàng tương tự bằng cách sử dụng JOIN nhưng làm thế nào để tìm sự khác biệt?

Tôi muốn điều này xảy ra trong một truy vấn DB mà không cần lặp lại từng mục để xóa nó.

Trả lời

0

Bạn đã xem toán tử LINQ except chưa?

Ví dụ:

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

Bạn không thể làm điều này với LINQ-to-SQL.

LINQ-to-SQL không tốt cho hoạt động hàng loạt - không thể thực hiện chèn hàng loạt, không thể thực hiện cập nhật hàng loạt và không thể xóa hàng loạt. Mọi đối tượng trong bộ sưu tập của bạn được xử lý riêng lẻ. Bạn có thể thực hiện tất cả các thao tác trong một giao dịch, nhưng sẽ luôn có một truy vấn cho mỗi bản ghi.

MSDN

Một lựa chọn tốt hơn là viết một thủ tục lưu trữ sẽ làm những gì bạn muốn.

0

PLINQO hỗ trợ thao tác xóa hàng loạt mà không truy xuất các thực thể trước tiên.

var delete = từ t trong TagsToPost chọn t) .Except (từ nt trong newList chọn nt, TagComparer mới())

context.Tags.Delete (xóa);

http://plinqo.com

0

Giải pháp của tôi cho phép bạn thực hiện xóa xác định bởi một trường lớp:

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

Cách sử dụng:

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

Nó chỉ làm việc với một lĩnh vực duy nhất, nhưng nó có thể là mở rộng đến các lĩnh vực tổng hợp một cách dễ dàng đủ.