具有实体框架6的多对多通用更新方法

时间:2015-09-28 19:56:56

标签: c# entity-framework orm dependency-injection entity-framework-6

我在抽象Update类中有一个用于实体框架的通用DatabaseOperations<T,U>方法:

public virtual void Update(T updatedObject, int key)
{
    if (updatedObject == null)
    {
        return;
    }

    using (var databaseContext = new U())
    {
        databaseContext.Database.Log = Console.Write; 

        T foundEntity = databaseContext.Set<T>().Find(key);
        databaseContext.Entry(foundEntity).CurrentValues.SetValues(updatedObject);
        databaseContext.SaveChanges();
    }
}

但是,这并不能处理多对多关系。

可以通过覆盖Update中的TrussSetDatabaseOperations : DatabaseOperations<TrussSet, TrussManagementDatabaseContext>方法来解决此多对多更新问题,如下所示:

public override void Update(TrussSet updatedTrussSet, int key)
{
    if (updatedTrussSet == null)
    {
        return;
    }

    using (var databaseContext = new TrussManagementDatabaseContext())
    {
        databaseContext.Database.Log = Console.Write;

        TrussSet foundTrussSet = databaseContext.TrussSets.Find(key);
        databaseContext.Entry(foundTrussSet).CurrentValues.SetValues(updatedTrussSet)            

        // Update the many-to-many relationship of TrussSets to Seals
        databaseContext.Entry(foundTrussSet).Collection(trussSet => trussSet.Seals).Load();
        databaseContext.Entry(foundTrussSet).Collection(trussSet => trussSet.Seals).CurrentValue = updatedTrussSet.Seals;

        databaseContext.SaveChanges();
    }
}

但是,这种重写会扩散到从DatabaseOperations继承并具有TrussSet对象的所有类。我可以以某种方式将添加的两行注入到通用更新方法中,以便为update方法提供集合属性,加载它们,并将相应的更新集合应用于该实体吗?提前谢谢。

1 个答案:

答案 0 :(得分:1)

查看您的代码,我想到了以下内容:

public virtual void Update(T updatedObject, int key, params string[] navigationProperties) {
    if (updatedObject == null) {
        return;
    }

    using (var databaseContext = new U()) {
        databaseContext.Database.Log = Console.Write;

        T foundEntity = databaseContext.Set<T>().Find(key);
        var entry = databaseContext.Entry(foundEntity);
        entry.CurrentValues.SetValues(updatedObject);                
        foreach (var prop in navigationProperties) {
            var collection  = entry.Collection(prop);
            collection.Load();
            collection.CurrentValue = typeof(T).GetProperty(prop).GetValue(updatedObject);
        }
        databaseContext.SaveChanges();
    }
}

如果您想要更多的类型安全性,也可以使用表达式而不是字符串(然后从这些表达式中提取属性名称)。

更新:这就是我的意思&#34;使用表达式&#34;在这种情况下:

public virtual void Update(T updatedObject, int key, params Expression<Func<T, IEnumerable>>[] navigationProperties) {
    if (updatedObject == null) {
        return;
    }


    using (var databaseContext = new U()) {
        databaseContext.Database.Log = Console.Write;

        T foundEntity = databaseContext.Set<T>().Find(key);
        var entry = databaseContext.Entry(foundEntity);
        entry.CurrentValues.SetValues(updatedObject);
        foreach (var prop in navigationProperties) {
            string memberName;
            var member = prop.Body as MemberExpression;
            if (member != null)
                memberName = member.Member.Name;
            else throw new Exception("One of the navigationProperties is not a member access expression");
            var collection = entry.Collection(memberName);
            collection.Load();
            collection.CurrentValue = typeof (T).GetProperty(memberName).GetValue(updatedObject);
        }
        databaseContext.SaveChanges();
    }
}