2009-03-17 13 views
5

を削除します。 TagsToPostsから複数のアイテムを削除する必要があります。 文字列を解析してIList<Tag> newTagsを作成しています。各タグには名前が付けられています。単一の投稿(TagsToPosts.PostId == mypostid)を指しているTagsToPostsのすべてのアイテムを削除したいとしています。Tagの名前はnewTagsではありません。例えばLINQは、私は、次のDBを持って

私はId = 1とつのポストを持っているが、3個のタグ:1 => "tag1", 2 => "tag2", 3 => "tag3"そして、多対多の関係テーブルTagsToPosts1 => 1, 1 => 2, 1 => 3 は、したがって、すべての3つのタグは、私のポストにリンクされています。 その後、文字列を解析して新しいIList<Tag> newList = new List<Tag>()を作成します。 newListは、0 => "tag1", 0 => "tag2"を含む。 新しいタグのリストに "tag3"という名前のタグが含まれていないため、テーブルのTagsToPostsから3番目のリレーションを削除します。だから私は違いを見つける必要があります。私はJOINを使用して同様のアイテムを見つけることができますが、違いを見つける方法を知っていますか?

これは、1つのDBクエリで、各アイテムを繰り返して削除することなく、この問題が起こることを望みます。

答えて

0

あなたはLinq Except演算子を見ましたか?例えば

:あなたはLINQツーSQLでこれを行うことはできません

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はバッチ操作には適していません。バッチ挿入は実行できません。バッチ更新はできず、バッチ削除はできません。コレクション内のすべてのオブジェクトは個別に扱われます。 1つのトランザクションですべての操作を実行できますが、常に各レコードのクエリがあります。

MSDN

より良いオプションは、あなたが欲しいものを行いますストアドプロシージャを記述することです。

0

PLINQOは、最初にエンティティを取得せずにバッチ削除操作をサポートしています。

varが削除= TagsToPostにおけるTからTを選択 ).Except(newListにおけるNTからは、NT選択 、新しいTagComparer())

context.Tags.Delete(削除)。

http://plinqo.com

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

これは、単一のフィールドで動作しますが、それができますフィールドを簡単に合成することができます。

関連する問題