我有以下情况:
我将如何在EntityFramework中实现这样的东西?
我的问题是,当我将UI直接绑定到实体的属性时,每个更改都会被实例化地应用到该实体。我希望将此延迟到用户按OK并实体被成功验证的时刻。
我考虑过用NoTracking加载实体,并在分离的实体验证后调用ApplyPropertyChanges,但我不完全确定正确的方法。MSDN上的EntityFramework的docu非常稀疏。
我可以想到的另一种方法是使用Refresh使用StoreWins来重新设置实体,但我不喜欢在Cancel上重置更改,而不喜欢在Ok应用更改。
有谁有好的教程或样本吗?
发布于 2009-05-02 01:22:02
一个选项是你说的做一个没有跟踪的查询。
ctx.Customers.MergeOption = MergeOption.NoTracking;
var customer = ctx.Customers.First(c => c.ID == 232);然后,客户可以根据内存中的需要修改'customer',并且上下文中实际上没有发生任何事情。
现在,当您想要进行更改时,您可以这样做:
// get the value from the database
var original = ctx.Customers.First(c => c.ID == customer.ID);
// copy values from the changed entity onto the original.
ctx.ApplyPropertyChanges(customer); .
ctx.SaveChanges();现在,如果您出于性能或并发原因对查询感到不舒服,可以添加一个新的扩展方法AttachAsModified(.)敬ObjectContext。
看起来是这样的:
public static void AttachAsModified<T>(
this ObjectContext ctx,
string entitySet,
T entity)
{
ctx.AttachTo(entitySet, entity);
ObjectStateEntry entry =
ctx.ObjectStateManager.GetObjectStateEntry(entity);
// get all the property names
var propertyNames =
from s in entry.CurrentValues.DataRecordInfo.FieldMetadata
select s.FieldType.Name;
// mark every property as modified
foreach(var propertyName in propertyNames)
{
entry.SetModifiedProperty(propertyName);
}
}现在您可以编写如下代码:
ctx.Customers.MergeOption = MergeOption.NoTracking;
var customer = ctx.Customers.First();
// make changes to the customer in the form
ctx.AttachAsModified("Customers", customer);
ctx.SaveChanges();现在您没有并发查询或外部查询。
现在唯一的问题是处理FK属性。您可能应该在这里查看我的提示索引:http://blogs.msdn.com/alexj/archive/2009/03/26/index-of-tips.aspx
希望这能有所帮助
亚历克斯
发布于 2009-04-29 16:28:20
正常的方法是绑定到实现IEditableObject的东西。如果以及如何与实体框架相匹配,我不确定。
发布于 2009-04-29 18:55:17
我也建议IEditableObject,另外还有IDataErrorInfo。
我的方法是,我基本上有一个以实体为构造函数参数的实体的视图模型(基本上是一个包装器对象)。
在BeginEdit中,我将实体属性复制到视图模型中,因此如果我执行CancelEdit,数据只在viewmodel中更改,而原始实体没有更改。在EndEdit中,我只是再次将ViewModel属性应用于实体,或者只有在验证成功的情况下才会这样做。
为了验证,我使用了IDataErrorInfo的方法。我只是实现了IDataErrorInfo.Error,以便它通过IDataErrorInfostring columnName检查每个属性名,并连接最终的错误消息。如果是空的,一切都好。(不确定错误是否意味着要以这种方式使用,但我做到了)
如果有其他实体附加到原始实体(如Customer.Orders ),则在原始实体的ViewModel中以嵌套ViewModels的形式创建它们。最初的ViewModel在自己的方法实现中调用subModels‘Error、Cancel-、EndEdit /Error方法。
这需要做更多的工作,但我认为这是值得的,因为在BeginEdit和EndEdit之间,您可以很好地确定在没有注意到的情况下,没有任何变化。而且,为INotifyPropertyChanged特性提供一个代码片段也很有帮助。
https://stackoverflow.com/questions/803022
复制相似问题