我正在使用EF4 POCO和UnitOfWork /存储库模式与MVC 3.我试图了解如何修改要插入的新记录。
我的插入/更新服务方法看起来像这样(存储库通过IoC注入服务构造函数):
public void UpdateData(Guid id, int newValue)
{
MyPoco poco = _repository.FirstOrDefault(p => p.Id = id);
if (poco == null)
{
poco = new Poco
{
//set properties
};
_repository.Add(poco);
}
poco.SomeFieldToUpdate = newValue;
}
我的更改通过我的UnitOfWork在我的控制器上的UseUnitOfWorkAttribute操作过滤器上保留:
void IResultFilter.OnResultExecuted(ResultExecutedContext filterContext)
{
var unitOfWork = IoCFactory.Instance.CurrentContainer.Resolve<IUnitOfWork>();
unitOfWork.Commit();
}
当然,如果只针对现有数据或新数据点击一次,这样可以正常工作。如果它已经存在,它在多次通过时工作正常。
但是如果表中不存在Guid值,那么如果多次调用它,它会尝试多次插入。
这就是我的困境。我理解为什么这不起作用,我只是不确定正确的解决方法。基本上,我需要以某种方式获取UnitOfWork中现有POCO的引用,并以某种方式更新它。但UnitOfWork在我的服务中没有提供(按设计) - 我甚至不确定我是否知道如何从UoW中提取实体并进行更新。
我是在做错了还是在这里忽略了一些简单的事情?或者我是如何设计这个的根本缺陷?我有一种感觉,我可能会比现在更努力。
提前致谢。
答案 0 :(得分:2)
发生这种情况的原因是因为您的实体尚未保存,而您执行查询以获取它。查询将无法在数据库中找到它并正确返回null。
您不应该使用存储库/工作单元/ ObjectContex
作为服务调用中未保存实体的内部存储。如果您需要它,您应该检查您的应用程序设计并重构它,因为可能有些错误。
无论如何,你可以从上下文中获取未保存的实体,但它不是很好的代码。您需要在存储库中使用特殊方法来按ID获取实体。您将使用它而不是调用FirstOrDefault
。类似的东西:
public MyPoco GetById(Guid id)
{
MyPoco enity = context.ObjectStateManager.GetObjectStateEntries(EntityState.Added)
.Where(e => e.Entity != null && e.Entity.GetType() == typeof(MyPoco)))
.Select(e => (MyPoco)e.Entity)
.Where(p => p.Id == id)
.SingleOrDefault();
if (entity == null)
{
entity = context.MyPocos.FirstOrDefault(p => p.Id == id);
}
}
答案 1 :(得分:0)
您是否将传递给UpdateData
的ID设置为新Poco对象上的键,如下所示:
poco = new Poco
{
Id = id;
//set properties
};
如果是,您可以查询不是FirstOrDefault
的对象,而是使用存储库方法中的TryGetObjectByKey
:
public Poco GetPocoByKey(Guid id)
{
EntityKey key = new EntityKey("MyEntities.Pocos", "Id", id);
object pocoObject;
if (context.TryGetObjectByKey(key, out pocoObject))
return (Poco)pocoObject;
return null;
}
优点是TryGetObjectByKey
如果可以找到具有指定键的对象,则首先查看ObjectContext。只有在没有的情况下,才会查询数据库。由于您在第一次找不到时将新Poco添加到上下文中,TryGetObjectByKey应该在您第二次使用相同键搜索对象时在上下文中找到它,即使它尚未保存到数据库中
编辑:此解决方案不起作用!
因为TryGetObjectByKey
找不到ObjectContext中处于added
状态的对象的密钥,即使密钥不是DB生成的密钥并且由应用程序提供,也不会找到密钥(请参阅下面的注释)