c# – 实体框架6 – DataServiceContext检测有更改

我有一个运行Entity Framework 6的WCF服务器应用程序.

我的客户端应用程序通过DataServiceContext从服务器消耗OData,在我的客户端代码中,我希望能够在上下文中调用HasChanges()方法,以查看其中的任何数据是否已更改.

我尝试使用以下扩展方法:

    public static bool HasChanges(this  DataServiceContext ctx)
    {
        // Return true if any Entities or links have changes
        return ctx.Entities.Any(ed => ed.State != EntityStates.Unchanged) || ctx.Links.Any(ld => ld.State != EntityStates.Unchanged);
    }

但它总是返回false,即使它正在跟踪的实体确实有变化.

例如,假设我有一个名为Customer的跟踪实体,则在调用SaveChanges()之前始终返回以下代码.

    Customer.Address1 = "Fred"
    if not ctx.HasChanges() then return
    ctx.UpdateObject(Customer)
    ctx.SaveChanges()

如果我注释掉if if ctx.HasChanges()然后返回代码行,则更改会成功保存,所以我很高兴实体已收到更改并能够保存它.

似乎上下文跟踪了这一变化,只是因为我无法从我的代码中确定这一事实.

谁能告诉我如何在DataServiceContext上确定HasChanges?

解决方法:

远.我刚刚阅读了DataServiceContext.UpdateObjectInternal(entity,failIfNotUnchanged),它是使用false参数直接从UpdateObject(实体)调用的.

逻辑如下:

>如果已修改,则返回; (短路)
>如果没有改变,抛出failIfNotUnchanged; (仅来自ChangeState())
>否则将状态设置为已修改. (没有发生数据检查)

所以从它的外观来看,UpdateObject并不关心/检查实体的内部状态,只关心状态枚举.这使得更新在没有更改时感觉有点不准确.

但是,我认为您的问题是在OP第二代码块中,您在调用UpdateObject之前检查扩展HasChanges.这些实体只是美化的POCO(您可以在Reference.cs中阅读(显示隐藏文件,然后在服务参考下).它们具有明显的属性和一些操作来通知有关更改.他们内部没有做的是跟踪状态.实际上,有一个与实体相关联的EntityDescriptor,它负责EntityTracker.TryGetEntityDescriptor(entity)中的状态跟踪.

底线是操作实际上非常简单,我认为你只需要使你的代码像

Customer.Address1 = "Fred";
ctx.UpdateObject(Customer);
if (!ctx.HasChanges()) return;
ctx.SaveChanges();

虽然我们现在知道,但这总是会报告HasChanges == true,所以你也可以跳过检查.

但不要绝望!您的服务引用提供的部分类可以扩展为完全符合您的要求.它完全是样板代码,因此您可能想要编写.tt或其他一些代码.无论如何,只需将其调整为您的实体:

namespace ODataClient.ServiceReference1  // Match the namespace of the Reference.cs partial class
{
    public partial class Books  // Your entity
    {
        public bool HasChanges { get; set; } = false;  // Your new property!

        partial void OnIdChanging(int value)  // Boilerplate
        {
            if (Id.Equals(value)) return;
            HasChanges = true;
        }

        partial void OnBookNameChanging(string value)  // Boilerplate
        {
            if (BookName == null || BookName.Equals(value)) return;
            HasChanges = true;
        }
        // etc, ad nauseam
    }
    // etc, ad nauseam
}

但是现在这很有效,并且与OP表达相似:

var book = context.Books.Where(x => x.Id == 2).SingleOrDefault();
book.BookName = "W00t!";
Console.WriteLine(book.HasChanges);

HTH!

上一篇:(转)Python爬虫学习笔记(2):Python正则表达式指南


下一篇:LayoutInflater.java (android-19)