linq

2009-03-17 22 views
5
Aşağıdaki DB var

silin. Aşağıdaki şekilde TagsToPosts'dan birden çok öğeyi silmem gerek. Bir dizeyi ayrıştırarak IList<Tag> newTags yapıyorum. Her etiketin adı vardır. Tek bir gönderiyi (TagsToPosts.PostId == mypostid) işaret eden tüm TagsToPosts öğelerini silmek istiyorum ve bu, newTags numaralı telefon numaramda olmayan Tag işaretini gösteriyor. Örneğinlinq

Ben Id = 1, üç etiketleri ile bir yazı vardır: 1 => "tag1", 2 => "tag2", 3 => "tag3" Ve ManyToMany ilişkiler tablo TagsToPosts: 1 => 1, 1 => 2, 1 => 3 Yani her üç etiketler görevime geri bağlantılıdır. Bundan sonra bir dizeyi ayrıştırarak yeni bir IList<Tag> newList = new List<Tag>() oluşturacağım. newList içerir: 0 => "tag1", 0 => "tag2". Şimdi, yeni etiketler listemin "tag3" isminde bir etiket içermediğinden, TagsToPosts tablosundaki üçüncü ilişkiyi kaldırmak istiyorum. Yani bir fark bulmam gerek. JOIN kullanarak benzer öğeleri bulabildiğimi biliyorum, ancak fark nasıl bulabilirim?

Bunu silmek için her bir öğeyi yinelemeden tek bir DB sorgusunda gerçekleşmesini istiyorum.

cevap

0

Linq Except operatörüne baktınız mı? Örneğin

: Sen LINQ-to-SQL ile bunu yapamaz

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

.

LINQ-to-SQL toplu işlemler için iyi değildir - toplu iş ekleri yapamaz, toplu güncelleştirme yapamaz ve toplu silme yapamaz. Koleksiyonunuzdaki her nesne ayrı ayrı ele alınır. Tüm işlemleri tek bir işlemde yapabilirsiniz, ancak her kayıt için her zaman bir sorgu olacaktır.

MSDN

Daha iyi bir seçenek istediğini yapacak bir saklı yordam yazmak.

0

PLINQO, ilk önce varlıkları almadan toplu silme işlemlerini destekler.

var (nt seçmek newlist içinde NT, yeni TagComparer() TagsToPost seçme t) .Except içinde t = silme)

context.Tags.Delete (sil);

http://plinqo.com

0
bir sınıf alan tarafından belirlenen silme işlemi yapmak sağlayan

Çözümümün:

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

Kullanımı:

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

Sadece tek bir alanla çalışır, ancak olabilir Kompozit alanlara yeterince genişletilmiş.