尝试删除实体框架 CTP5 中的 POCO 对象时遇到问题
我在尝试使用实体框架 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
你是对的。删除只是 Attach 的包装并将状态设置为已删除 - 这是 ObjectContext(包装在 DbContext 中)知道它必须删除对象的唯一方法。
我想您可以尝试使用
DbSet
-Local
的新 CTP5 功能,并首先尝试查找具有相同 ID 的附加实体: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: