使用Linq更新Master表时更新子记录的有效方法

时间:2012-05-31 11:27:47

标签: c# linq linq-to-sql entity-framework-4 linq-to-entities

我目前使用的是一般的repositry类,只能更新单个表

public abstract class MyRepository<T> : IRepository<T>
        where T : class
{


    protected IObjectSet<T> _objectSet;
    protected ObjectContext _context;

    public MyRepository(ObjectContext Context)
    {
        _objectSet = Context.CreateObjectSet<T>();
        _context = Context;
    }


    public IQueryable<T> GetAll()
    {
        return _objectSet.AsQueryable();
    }

    public IQueryable<T> Find(Expression<Func<T, bool>> filter)
    {
        return _objectSet.Where(filter);
    }

    public void Add(T entity)
    {
        _objectSet.AddObject(entity);
        _context.ObjectStateManager.ChangeObjectState(entity, System.Data.EntityState.Added);
        _context.SaveChanges();
    }

    public void Update(T entity)
    {
        _context.ObjectStateManager.ChangeObjectState(entity, System.Data.EntityState.Modified);
        _context.SaveChanges();
    }

    public void Delete(T entity)
    {
        _objectSet.Attach(entity);
        _context.ObjectStateManager.ChangeObjectState(entity, System.Data.EntityState.Deleted);
        _objectSet.DeleteObject(entity);
        _context.SaveChanges();
    }

}

对于我的EDMX设计器生成的每个表类,我创建了另一个类

public class CustomerRepo : MyRepository<Customer>
{
    public CustomerRepo (ObjectContext context)
        : base(context)
    {

    }
}

对于我需要对特定表进行的任何更新,我执行此操作:

Customer CustomerObj = new Customer();
CustomerObj.Prop1 = ...
CustomerObj.Prop2 = ...
CustomerObj.Prop3 = ...
CustomerRepo.Update(CustomerObj);

当我更新到名为Customer的特定表时,这非常有效。现在,如果我还需要更新另一个表的另一个表的每一行,这是一个名为Orders的子项,那么我需要对MyRepository类进行哪些更改。订单表将具有Customer记录和多个字段的多个记录,例如Field1,Field2,Field3。

所以我的问题是:1。)如果我只需要根据条件更新Orders表的Field1以及基于不同条件的某些其他行的Field2,那么我需要做哪些更改?

2.。)如果没有这样的条件并且所有子行都需要使用相同的值更新所有行,那么我需要做哪些更改?

感谢您抽出宝贵时间。期待您的投入......

1 个答案:

答案 0 :(得分:1)

您的主要问题是您尝试更新断开连接的实体(即var myCustomer = new Customer())而不将其附加到数据上下文。有关如何附加断开连接的实体的详细信息,请参阅this answer。在您的情况下,我认为这可能会变得复杂,因为不仅需要附加父实体,还需要附加所有子实体。

在您的情况下,我的建议是对首先从上下文检索的实体执行更新,因此已经附加到它上面。在这种情况下,这些实体将自己跟踪更改。您无需将实体附加到您的上下文或致电_context.ObjectStateManager.ChangeObjectState。再次,请查看the same answer I mentioned earlier以获取对附加实体执行更新的示例。加载父对象后,您只需对其及其子项应用任何更改,然后在完成所有操作后再调用上下文中的SaveChanges方法。

注意:默认情况下,EF会延迟加载任何子关系(即子对象,集合等)。但是,在某些情况下,您可能希望在加载父对象的同时显式/急切地加载子对象,而不是延迟加载(您可以找到文档here)。