尝试删除实体框架 CTP5 中的 POCO 对象时遇到问题

发布于 2024-10-15 02:17:30 字数 2040 浏览 0 评论 0原文

我在尝试使用实体框架 CTP5 代码删除 POCO 对象时遇到问题。

我将从我的 Delete 方法开始,然后进行两个集成测试。第一个集成测试通过/有效,第二个则没有。

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

  ...
}

这就是我带有删除方法的通用存储库。

好的..现在到我的集成测试....

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

第二个抛出以下异常:-

System.InvalidOperationException:一个 已经具有相同键的对象 存在于 ObjectStateManager 中。这 ObjectStateManager 无法跟踪 具有相同密钥的多个对象。

现在,如果我理解正确的话,我正在尝试将第二个 Poco 对象(即 detachedPoco)添加到对象图..但我不能,因为一个已经存在(existingPoco 我已预加载)。好吧……但我觉得我不应该关心这个。作为消费者,我不想关心这些对象管理器之类的东西。我只想保存/删除我的 poco。

如何更改删除方法以反映这些情况?请?

I'm having a problem trying to delete a POCO object with my Entity Framework CTP5 code.

I'll start out with my Delete method and then both Integration Tests. First Integration Test passes/works, second doesn't.

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

  ...
}

So that's my generic repo with a Delete method.

Ok.. now to my Integration Tests....

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

that works, this doesn't...

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

This second one throws the following exception :-

System.InvalidOperationException: An
object with the same key already
exists in the ObjectStateManager. The
ObjectStateManager cannot track
multiple objects with the same key.

Now, if I understand that correctly, I'm trying to add a second Poco object (ie detachedPoco) to the Object Graph .. but I can't because one already exists (the existingPoco I pre-loaded). Ok ... but I feel like I shouldn't care about this. As a consumer, I don't want to care about these ObjectManagers and stuff. I just want to have my poco's just save/delete.

How can I change my Delete method to reflect these scenarios? Please?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

知你几分 2024-10-22 02:17:30

你是对的。删除只是 Attach 的包装并将状态设置为已删除 - 这是 ObjectContext(包装在 DbContext 中)知道它必须删除对象的唯一方法。

我想您可以尝试使用 DbSet - Local 的新 CTP5 功能,并首先尝试查找具有相同 ID 的附加实体:

var attached = Context.Set<T>().Local.FirstOrDefault(e => e.Id == entity.Id);
if (attached != null)
{
 // Delete attached
}
else
{
 // Delete entity
}

You are right. Deleting is just wrapper around Attach and set state to Deleted - it is the only way how ObjectContext (wrapped in DbContext) can know that it has to delete object.

I guess you can try to use new CTP5 feature of DbSet - Local and try to find attached entity with the same Id first:

var attached = Context.Set<T>().Local.FirstOrDefault(e => e.Id == entity.Id);
if (attached != null)
{
 // Delete attached
}
else
{
 // Delete entity
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文