【问题标题】:Dynamic LINQ - Entity Framework 6 - Update Records for Dynamic Select动态 LINQ - 实体框架 6 - 动态选择的更新记录
【发布时间】:2016-11-01 21:21:49
【问题描述】:

C#菜鸟。下面是我的代码,现在已经尝试了几个小时来更新我的数据库中的一些字段,并尝试了许多不同的实现,但没有运气。

        // Select all fields to update
        using (var db = new Entities())
        {
            // dbFields are trusted values
            var query = db.tblRecords
                         .Where("id == " + f.id)
                         .Select("new(" + string.Join(",", dbFields.Keys) + ")");

            foreach (var item in query)
            {
                foreach (PropertyInfo property in query.ElementType.GetProperties())
                {
                    if (dbFields.ContainsKey(property.Name))
                    {
                        // Set the value to view in debugger - should be dynamic cast eventually
                        var value = Convert.ToInt16(dbFields[property.Name]);
                        property.SetValue(item, value);

                        // Something like this throws error 'Object does not match target type'
                        // property.SetValue(query, item);
                    }
                }
            }
            db.SaveChanges();
        }

上面的代码在运行时不会对数据库产生任何变化。显然,这段代码需要一些清理,但我正在尝试让基本功能正常工作。我相信我可能需要做的是以某种方式将“项目”重新应用到“查询”中,但无论我尝试什么实现,我都没有运气让它工作,我总是收到“对象与目标类型不匹配” .

这个半相似的问题重申了这一点,但对我来说不是很清楚,因为我使用的是动态 LINQ 查询并且不能直接引用属性名称。 https://stackoverflow.com/a/25898203/3333134

【问题讨论】:

  • 你为什么需要这个Select("new ...?如果您删除 Select,您将拥有来自 tblRecords 的实体。更改这些将导致 EF 跟踪的更改。

标签: c# entity-framework-6 dynamic-linq


【解决方案1】:

Entity Framework 将为您执行实体更新,而不是自定义结果。您的 tblRecords 包含许多实体,如果您希望 Entity Framework 提供帮助,这就是您想要操作的内容。删除您的投影(对Select 的调用),查询将直接返回对象(列太多,是的,但我们稍后会介绍)。

动态更新的执行方式与 C# 中的任何其他动态分配相同,因为您可以使用普通对象。 Entity Framework 将跟踪您所做的更改,并在调用 SaveChanges 时生成并执行相应的 SQL 查询。

然而,如果您想优化并停止选择和创建内存中的所有值,即使是那些不需要的值,您也可以从内存中执行更新。如果您自己创建了正确类型的对象并分配了正确的 ID,则可以使用 Attach() 方法将其添加到当前上下文中。从那时起,Entity Framework 将记录任何更改,当您调用SaveChanges 时,所有内容都应发送到数据库:

// Select all fields to update
using (var db = new Entities())
{
    // Assuming the entity contained in tblRecords is named "ObjRecord"
    // Also assuming that the entity has a key named "id"
    var objToUpdate = new ObjRecord { id = f.id };

    // Any changes made to the object so far won't be considered by EF

    // Attach the object to the context
    db.tblRecords.Attach(objToUpdate);

    // EF now tracks the object, any new changes will be applied

    foreach (PropertyInfo property in typeof(ObjRecord).GetProperties())
    {
        if (dbFields.ContainsKey(property.Name))
        {
             // Set the value to view in debugger - should be dynamic cast eventually
             var value = Convert.ToInt16(dbFields[property.Name]);
             property.SetValue(objToUpdate, value);
        }
    }

    // Will only perform an UPDATE query, no SELECT at all
    db.SaveChanges();
}

【讨论】:

  • 工作并且使 1000 倍更有意义感谢您的帮助!它认为应该是 db.ObjRecord.Attach(objToUpdate) 而不是 db.Attach(objToUpdate)。再次感谢!
  • @user3333134 绝对是,我的错。这就是你凭记忆输入的结果!
【解决方案2】:

当您执行SELECT NEW ... 时,它只会选择特定字段并且不会为您跟踪更新。我认为,如果您将查询更改为这样,它将起作用:

var query = db.tblRecords.Where(x=>x.id == id);

【讨论】:

    猜你喜欢
    • 2017-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多