C# 实体框架POCO-如果字段更新两次,如何防止错误?
我开始在模型优先配置中使用POCO的实体框架。我有一个稍微非标准的模型-通过自定义.tt文件来响应.edmx中的自定义属性生成,使我能够触发NotifyPropertyChanged事件来记录对某些属性的更新-这导致一个类实际上看起来有点像这样:C# 实体框架POCO-如果字段更新两次,如何防止错误?,c#,entity-framework,poco,C#,Entity Framework,Poco,我开始在模型优先配置中使用POCO的实体框架。我有一个稍微非标准的模型-通过自定义.tt文件来响应.edmx中的自定义属性生成,使我能够触发NotifyPropertyChanged事件来记录对某些属性的更新-这导致一个类实际上看起来有点像这样: public partial class MyClass: INotifyPropertyChanged { /// <summary> /// Catches events to be added to the UserL
public partial class MyClass: INotifyPropertyChanged
{
/// <summary>
/// Catches events to be added to the UserLog
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Notifies any event listeners attached to the PropertyChanged event that a loggable field
/// update has occurred.
/// </summary>
/// <param name="eventType">The type of the field.</param>
/// <param name="message">The message to record in the logs</param>
private void NotifyFieldUpdate(string eventType, string message)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new LogEventArgs(eventType, message));
}
}
private string _myField;
public virtual string MyField
{
get
{
return _myField;
}
set
{
if ( _myField != value )
{
_myField = value;
NotifyFieldUpdate( "FIELDCHANGE", String.Format("MyField changed to {0}", value) );
}
}
}
}
在调用第二个方法时,我遇到了以下错误:
调用EntityMemberChanged或EntityComplexMemberChanged时,未首先调用具有相同属性名称的同一更改跟踪程序上的EntityMemberChanged或EntityComplexMemberChanged。有关正确报告更改的信息,请参阅实体框架文档
我试过使用currentContext.DetectChanges()
和currentContext.Refresh(…)
,但那确实是猴子编码,因为我不知道到底发生了什么
我的第一个问题是:是什么导致了问题,为了避免这种类型的错误,我必须对ObjectContext做些什么?在我看来,字段可能会不时更新似乎很有道理,如果发生两次,我不希望我的系统崩溃
我的第二个可能更深入的问题是:当类似乎已经触发了这些
EntityMemberChanged
事件时,我是否使用INotifyPropertyChanged
接口来处理这一切都是错误的?我假设这是因为ObjectContext正在创建代理—这是否意味着在某些情况下,如果我没有自己的通知,这些方法可能不可用 我认为这是因为您正在将ObjectContext传递给UI线程,而它不是线程安全的
我认为您是对的,您需要重新思考如何处理这个问题(主要是对PropertyChanged事件的数据访问)
请参阅此处的备注部分:事实证明,正如我所怀疑的,问题的根本原因与我的
ObjectContext
创建代理有关
为了解决这个错误,在我的例子中,最终解决这个问题,我只需要添加
currentContext.ContextOptions.ProxyCreationEnabled = false;
创建ObjectContext并阻止它创建代理。这可能会给我带来一些便利,但考虑到它们看起来有些脆弱和不透明,我认为这暂时为我节省了很多麻烦
有用资源:我认为第一次没有调用您的事件时,只有第二次。也许您应该尝试使用实体框架中的事件。
选中链接如果无法禁用代理并具有虚拟时间戳列,请不要为此属性调用RaisePropertyChanged 这在单元测试中会是相同的吗,这就是产生这种情况的原因?我想知道事件处理程序委托是否在自己的线程中运行。但是它也在
MyClass
对象中运行,所以肯定会在同一个线程中发生吗?当然…如果你禁用代理,你会跳过很多,比如懒散地加载孩子。而且,它可能会破坏他现有的模型。模型似乎不会受到它的影响-能够懒洋洋地加载子对象肯定会很方便,但是当我更新对象时让我的代码崩溃是非常不方便的,从这里的答案来看,没有人知道如何避免这种情况。在我花了几个小时说服Entity Framework创建代理之后,我遇到了同样的问题,这样我就可以比DetectChanges()获得巨大的性能优势。这个答案远远不是正确的解决方案!那是当时为我工作的。如果你有一个正确的解决方案,一定要添加它!这也是基于EF4的,现在有几个版本,所以技术可能已经改变了。这个问题似乎是由ObjectContext代理引起的,据我所知,它不能被更新多次。禁用代理,然后//禁用代理对象创建。context.ContextOptions.ProxyCreationEnabled=false;事实上,正如我在下面提到的,这就是我最终选择的方法。
currentContext.ContextOptions.ProxyCreationEnabled = false;