实体框架实体状态未经任何修改即被修改

时间:2013-04-28 16:39:05

标签: c# entity-framework

我对更新实体有以下问题。下面给出的是我的WCF方法。 (在确定是否更新或添加后,通过公共保存方法调用更新)

protected bool UpdateSalesMaster(SalesMaster order)
{
    using (var context = new MyContext())
    {
        SalesMaster original = context.SalesMasters.FirstOrDefault(o => o.OrderID == order.OrderID);

        if (original != null)
        {
            context.Entry(original).CurrentValues.SetValues(order);

            foreach (SalesDetail detail in order.SalesDetails)
            {
                if (detail.OrderDetailID == 0)
                    context.SalesDetails.Add(detail);
                else
                {
                    SalesDetails originalDetail = context.SalesDetails.FirstOrDefault(o => o.OrderDetailID == detail.OrderDetailID);
                    if (originalDetail != null)
                        context.Entry(originalDetail).CurrentValues.SetValues(detail);
                }
            }

            context.SaveChanges();
            return true;
        }
        else
        {
            throw new FaultException(string.Format("Invalid Order specified: {0}", order.OrderID));
        }
    }
}

当我刚刚更新SalesMaster中的OrderDate并且不更改任何详细信息时,会向数据库触发更新查询以获取详细信息。我希望只能看到SalesMaster的Update查询。

有人能让我知道我在这里做错了什么吗?如果没有更改,我不想向DB发送更新查询。

我使用从数据库中获取原始值的方法来确定是否使用context.Entry(originalDetail)更新任何值.CurrentValues.SetValues(detail);

我还通过检查实体的IAuditable实现来覆盖SaveChanges来设置LastModified日期。这是当我发现详细实体的状态被识别为已修改时。但是在DB中发生的唯一更新是LastModifiedBy,它在我的保存更改中更新。我不确定当没有任何细节变化时它是如何设置为Modified状态的。

public override int SaveChanges()
{
    var changeSet = ChangeTracker.Entries<IAuditable>();

    if (changeSet != null)
    {
        foreach (var entry in changeSet.Where(c => c.State != EntityState.Unchanged))
        {
            if (entry.State == EntityState.Added)
                entry.Entity.DateCreated = DateTime.Now;

            if (entry.State == EntityState.Modified)
            {
                entry.Property(a => a.CreatedByUser).IsModified = false;
                entry.Property(a => a.DateCreated).IsModified = false;
            }
            entry.Entity.DateModified = DateTime.Now;
        }
    }
    try
    {
        return base.SaveChanges();
    }
    catch (DbEntityValidationException ex)
    {
        throw ex;
    }

}

我的解决方案结构是:

  1. 客户端 - Windows窗体UI
  2. 实体 - POCO作为单独的库
  3. WCF - 所有业务逻辑,添加,更新,删除对象。
  4. 数据 - 使用Fluent映射的实体框架上下文。

1 个答案:

答案 0 :(得分:0)

根据您设置POCO的方式,EF将默认使用两种方法之一来检查实体的更改。

如果所有POCO属性都是虚拟的,EF将使用继承POCO类型的代理对象,并覆盖所有属性以跟踪更改。

我假设在这种情况下,在整个对象上使用SetValues将触发脏标志,这将导致EF为数据库生成更新查询。

如果您没有使用代理,那么您的IAuditable实施将成为brumScouse建议的主要嫌疑人。