0

ObjectStateManager をクリアしたいのでSaveChanges();、DbContext を呼び出した後、次の行が結果を返さないようにします。

dbContext.ObjectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Unchanged);

動作は、ObjectStateManager 内のすべてのオブジェクト (Added、Modified) が State changed を取得するUnchangedように見えるため、コードはそれらすべてを返します。クリアする方法はありますか?

コンテキストを再利用し、変更されていない状態のエンティティに対していくつかのことを行うため、これが必要ですが、ObjectSateManager は変更されていないエンティティで成長し、成長するため (SaveChanges 後にすべてが変更されないため)、1 つのエンティティに対して同じ作業を繰り返します。以上。

編集:

デタッチ方法が機能しない理由:

2 つのクラスがあるとします。

public class Nation
{
    public string Name { get; set; }
    public ICollection<City> Cities { get; set; }
}

public class City
{
    public string Name { get; set; }
    public Nation Nation { get; set; }
}

これで、更新または挿入する必要のあるいくつかの都市を含む Nation Item を SaveChanges に渡しました。

次のように仮定します。

var canada = new Nation()
{
    Name = "Canada",
}

canada.Cities = new City[] 
    { 
        new City(){ Name = "Ottawa", Nation = canada, }, 
        new City(){ Name = "Edmonton", Nation = canada, }, 
        new City(){ Name = "Victoria", Nation = canada, }, 
        new City(){ Name = "Torronto", Nation = canada, } 
    },
}

これで、これらすべてのオブジェクトが ObjectStateManager 内の Unchanged 状態になりました。(SaveChanges 呼び出しの後)

私はそれらをループし、状態を未変更に設定します。これにより、すべての都市がNation = nullとを持つことになりNation.Cities being emptyます。

4

3 に答える 3

0

できることは、ページングを使用することです。DbContextN 個のオブジェクトごとに新しいものを作成しますが、それらはすべて同じ接続とトランザクションを使用します。

于 2014-02-11T21:51:54.427 に答える
0

DetachメソッドはObjectContext、オブジェクト コンテキストからそれを削除します。

dbContext.ObjectContext.Detach( entity );

また、エンティティを添付する必要がない場合は、AsNoTracking()拡張メソッドを使用できます。追跡せずにクエリを実行します。

var items = dbContext.Items.AsNoTracking().Where(...);
于 2014-02-11T20:25:22.370 に答える
0

「完全に」機能するソリューションを見つけました。ObjectStateManger をクリアしませんが、以前に添付/処理されたエンティティをすべて無視します。

private static int __lastProcessedIndex = 0;
private static DbContext _oldContext = null;

public void DoYourMagic(DbContext context)
{
    if (ReferenceEquals(context, _oldContext) == false)
    {
        _oldContext = context;
        _lastProcessedIndex = 0;
    }

    var objectContext = (context as IObjectContextAdapter).ObjectContext;
    var unchanged = objectContext.ObjectStateManager.GetObjectSateEntires(EntityState.Unchanged).ToArray();

    for (int i = _lastProcessedIndex; i < unchanged.Length; i++)
    {
        //do your magic with unchanged entities...
    }

    context.SaveChanges();

    //Now all entries in objectstatemanager are in state Unchanged
    //I am setting the index to the Count() - 1
    //So that my next call of the method "DoYourMagic" starts the for with this index
    //This will than ignore all the previously attached ones
    _lastProcessedIndex = objectContext.ObjectStateManager.GetObjectSateEntires(EntityState.Unchanged).Count();
}
于 2014-02-12T15:18:14.193 に答える