2

Entity Framework CTP5 コードで POCO オブジェクトを削除しようとすると問題が発生します。

私は自分のDelete方法から始めて、次に両方の統合テストを行います。最初の統合テストは成功/機能しますが、2 つ目は失敗します。

public class GenericRepository<T> : IRepository<T> where T : class
{
  public GenericRepository(DbContext unitOfWork)
  {
    Context = unitOfWork;
  }

  ...

  public void Delete(T entity)
  {
    if (entity == null)
    {
      throw new ArgumentNullException("entity");
    }

    if (Context.Entry(entity).State == EntityState.Detached)
    {
      Context.Entry(entity).State = EntityState.Deleted;
    }
    Context.Set<T>().Remove(entity);
  }

  ...
}

これが、Delete メソッドを使用した汎用リポジトリです。

わかりました..今、私の統合テストに....

[TestMethod]
public void DirectlyDeleteAPoco()
{
  // Arrange.
  var poco = new Poco {PocoId = 1};

  // Act.
  using (new TransactionScope())
  {
    PocoRepository.Delete(poco);
    UnitOfWork.Commit();

    // Now try and reload this deleted object.
    var pocoShouldNotExist =
      PocoRepository.Find()
      .WithId(1)
      .SingleOrDefault();

    Assert.IsNull(pocoShouldNotExist);
  }
}

それは機能しますが、これは機能しません...

[TestMethod]
public void DeleteAPocoAfterLoadingAnInstance()
{
  // Arrange.
  var existingPoco = PocoRepository.Find().First();
  var detachedPoco = new Poco {PocoId = existingPoco.PocoId};

  // Act.
  using (new TransactionScope())
  {
    PocoRepository.Delete(detachedPoco );
    UnitOfWork.Commit();

    // Now try and reload this deleted object.
    var pocoShouldNotExist =
      PocoRepository.Find()
      .WithId(existingPoco.PocoId)
      .SingleOrDefault();

    Assert.IsNull(pocoShouldNotExist);
  }
}

この 2 番目のものは、次の例外をスローします:-

System.InvalidOperationException: 同じキーを持つオブジェクトが ObjectStateManager に既に存在します。ObjectStateManager は、同じキーを持つ複数のオブジェクトを追跡できません。

detachedPocoさて、それが正しく理解できれば、2 つ目の Poco オブジェクト (つまり) をオブジェクト グラフに追加しようとしていexistingPocoます。わかりました...しかし、私はこれを気にするべきではないように感じます. 消費者として、私はこれらの ObjectManagers などを気にしたくありません。ポコを保存/削除するだけにしたいだけです。

これらのシナリオを反映するように Delete メソッドを変更するにはどうすればよいですか? お願いします?

4

1 に答える 1

1

あなたが正しいです。削除は、Attach の単なるラッパーであり、状態を Deleted に設定します。これは、ObjectContext (DbContext にラップされている) がオブジェクトを削除する必要があることを知る唯一の方法です。

DbSet-の新しい CTP5 機能を使用Localして、最初に同じ ID を持つ接続されたエンティティを見つけようとすることができると思います。

var attached = Context.Set<T>().Local.FirstOrDefault(e => e.Id == entity.Id);
if (attached != null)
{
 // Delete attached
}
else
{
 // Delete entity
}
于 2011-01-31T13:03:44.513 に答える