c# - Entity Framework 6 的多对多通用更新方法

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

我有一个通用的 Update抽象 Entity Framework 的方法 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 对象。我能否以某种方式将添加的两行注入(inject)通用更新方法,以便为更新方法提供集合属性、加载它们并将相应的更新集合应用于该实体?提前致谢。

最佳答案

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

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();
    }
}

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

更新:这里是我在这种情况下所说的“使用表达式”的意思:

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();
    }
}

关于c# - Entity Framework 6 的多对多通用更新方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32830764/

相关文章:

c# - 使用 DataContractSerializer 和 DataProtectionProvider 序列化和加密对象

c# - Entity Framework 中的动态排序

c# - 支持 Medium Trust 和 POCO 的 .Net 3.5 ORM

java - 映射到同一外键的多个字段的 JPA 映射

c# - 如何使 serviceStack.ormlite 或 Dapper 中的映射依赖于列类型?

C# 网页浏览器更改源代码

c# - 为什么我的 .NET 启动时间随着预生成的序列化程序集而增加?

.net - Entity Framework 中的 DTO

c# - Entity Framework 4 约定

node.js - 在 Sequelize Model.create 上设置 raw = true