我正在使用Entity Framework构建数据输入应用程序,用户可以填写表单然后保存或取消。但是,如果存在可以保存到数据库的实际数据,我只希望启用“保存”按钮。
我知道DbContext.ChangeTracker。但是,无论何时发生变化,我都无法从上下文中获得通知。
我可以手动跟踪,但这很乏味且容易出错。
更新 该应用程序是一个WinForms应用程序
问题: 如何在DbContext“脏/有变化”时收到通知?
更新2
也许这可以澄清我的问题:
这是我不想要的:
using(var ctx = new DbContext()) {
var foo = new FooEntity();
ctx.Add(foo);
RaiseContextIsDirty(); //<-- don't want to do this, this should be automatic
//.....
ctx.SaveChanges();
RaiseContextIsClean(); //<-- don't want to do this, this should be automatic
}
我正在寻找的是这样的:
using(var ctx = new DbContext()) {
ctx.ChangeTracker.OnDirtyChanged += ContextDirtyChanged;
var foo = new FooEntity();
ctx.Add(foo); //<- fires OnDirtyChanged
//.....
ctx.SaveChanges(); //<- fires OnDirtyChanged
}
答案 0 :(得分:0)
您可以将此代码用于DbContext.HasUnsavedChanges
属性:
public partial class MyDBContext
{
public bool HasUnsavedChanges
{
get
{
try
{
return this.ChangeTracker.Entries().Any(e => e.State == EntityState.Added
|| e.State == EntityState.Modified
|| e.State == EntityState.Deleted);
}
catch (System.InvalidOperationException)
{
return false;
}
}
}
在WPF中,将其设置为WPF命令CanExecute
的{{1}}条件就足够了。
Windows窗体中的问题是,您需要找到一个经常触发的事件,并禁用或启用该按钮,但不要太频繁。我不认为EntityFramework中内置了任何可以向您提供此类事件的属性观察器。
您可以检查每个鼠标上的Save
或该表单上的关键事件或类似事件,这与WPF内部工作方式类似,请参阅 - http://northhorizon.net/2012/better-commands-in-wpf/。
答案 1 :(得分:0)
所以你可以对SaveChanges
:
public class MyDbContext : DbContext
{
public delegate void ChangeEventHandler(object sender, ChangeEventArgs e);
public event ChangeEventHandler ChangeEvent;
public override int SaveChanges()
{
var result = base.SaveChanges();
var entitiesAdded = this.ChangeTracker.Entries.Where(x => x.State == EntityState.Added);
var entitiesRemoved = this.ChangeTracker.Entries.Where(x => x.State == EntityState.Deleted);
var entitiesModified = this.ChangeTracker.Entries.Where(x => x.State == EntityState.Modified);
ChangeEvent(this, new ChangeEventArgs(entitiesAdded, entitiesRemoved, entitiesModified));
return result;
}
}
只需创建一个实现ChangeEventArgs
的类。{/ p>即可创建EventArgs
然后你应该能够以正常的方式绑定到事件:
ctx.ChangeEvent += (s, e) => Console.WriteLine("Changes happened");
我刚刚从MSDN中提取了大部分内容,我没有时间对其进行正确测试。但我不认为这个解决方案太过分了。
DbSet<T>
支持IDbSet<T>
,因此您无法实现自己的IDbSet<T>
,并且当您实施自己的Add
功能时in。这将采用与上述相同的模式。
然后在你的MyDbContext
中听取所有这些事件并将它们合并为1个事件或在它们到来时处理它们。