在实体对象上设置属性时,即使该值与以前完全相同,它也会将值保存到数据库中。反正有没有阻止这个?
示例:
如果我加载一个Movie对象并且Title是“A”,如果我再次将Title设置为“A”并且SaveChanges()我希望我不会在SqlProfiler中看到UPDATE语句,但我是。反正有没有阻止这个?
答案 0 :(得分:5)
是的,你可以改变这个。但是,在当前版本的实体框架中,这样做并非易事。将来会变得更容易。
您看到此行为的原因是因为实体模型的默认代码生成。这是一个代表性的例子:
public global::System.Guid Id
{
get
{
return this._Id;
}
set
{
// always!
this.OnIdChanging(value);
this.ReportPropertyChanging("Id");
this._Id = global::System.Data.Objects.DataClasses
.StructuralObject.SetValidValue(value);
this.ReportPropertyChanged("Id");
this.OnIdChanged();
}
}
private global::System.Guid _Id;
partial void OnIdChanging(global::System.Guid value);
partial void OnIdChanged();
此默认代码生成是合理的,因为实体框架不知道您打算如何使用这些值的语义。属性中的类型可能具有可比性,也可能不具有可比性,即使它们存在,框架也无法知道您在所有情况下如何使用引用相等与值相等。对于像小数这样的某些值类型,它非常清楚,但从一般意义上说它并不明显。
另一方面,您知道您的代码,并可以自定义一些。麻烦的是这是生成的代码,因此您不能只是进入并编辑它。您需要接管代码生成,或者不必要。那么让我们来看看三个选项。
这里的基本方法是创建一个T4模板,该模板执行后面的代码,以及来自实体框架的默认代码生成。 Here is one example.此方法的一个优点是the Entity Framework will be moving to T4 generation in the next version,因此您的模板在将来的版本中可能会运行良好。
第二种方法是完全消除热电联产,do your change tracking support manually, via IPOCO。使用这种方法,您不需要更改代码的生成方式,也不会执行任何代码生成,而是通过实现多个接口为实体框架提供更改跟踪支持。有关更多详细信息,请参阅链接的帖子。
另一个选择是暂时使用实体框架,并等到下一个版本获得您想要的行为。 The next version of the Entity Framework will use T4 by default,因此自定义代码生成非常简单。
答案 1 :(得分:4)
根据MSDN:
更改对象的状态 无论何时改变都不变 属性设置器被调用。这发生了 即使设定的值是 与当前值相同。之后 调用AcceptAllChanges方法, state返回Unchanged。通过 默认情况下,调用AcceptAllChanges 在SaveChanges操作期间。
在更新之前,您似乎希望检查Entity对象的属性值,以防止UPDATE语句。
答案 2 :(得分:0)
在通用级别,如果您的实体正在实现INotifyPropertyChanged,那么如果值相同,则不希望触发PropertyChanged事件。所以每个属性都是这样的: -
public decimal Value
{
get
{
return _value;
}
set
{
if (_value != value)
{
_value = value;
if (_propertyChanged != null) _propertyChanged(this, new PropertyChangedEventArgs("Value"));
}
}
}
希望这与实体框架相关。
答案 3 :(得分:0)
您可以做的一件事就是使用部分类文件自己包装属性,然后使用您的属性而不是第一个:
public sealed partial class MyEFType {
public string MyWrappedProperty {
get {
return MyProperty;
}
set {
if (value == MyProperty)
return;
MyProperty = value;
}
}
}
对每个属性执行此操作是不切实际的,但如果您需要检测某个特定属性是否已实际更改而不是仅仅已写入,则类似这可行。