简体   繁体   English

动态LINQ-实体框架6-动态选择的更新记录

[英]Dynamic LINQ - Entity Framework 6 - Update Records for Dynamic Select

C# rookie. C#新秀。 Below is my code, been trying for hours now to get this to update some fields in my DB and tried many different implementations without luck. 下面是我的代码,已经尝试了几个小时才能使它更新数据库中的某些字段,并尝试了许多不同的实现,但是没有运气。

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

The above code when run does not result in any changes to the DB. 上面的代码在运行时不会导致对数据库的任何更改。 Obviously this code needs a bit of cleanup but i'm trying to get the basic functionality working. 显然,此代码需要一些清理,但是我正在尝试使基本功能正常工作。 I believe what I might need to do is to somehow reapply 'item' back into 'query' but I've had no luck getting that to work no matter what implementation I try i'm always receiving 'Object does not match target type'. 我相信我可能需要做的是以某种方式将“ item”重新应用到“ query”中,但是无论我尝试哪种实现方式,我总是没有运气让它正常工作,我总是收到“对象与目标类型不匹配” 。

This semi similar issue reaffirms that but isn't very clear to me since i'm using a Dynamic LINQ query and cannot just reference the property names directly. 这个半类似的问题重申了这一点,但我不太清楚,因为我使用的是动态LINQ查询,不能直接引用属性名称。 https://stackoverflow.com/a/25898203/3333134 https://stackoverflow.com/a/25898203/3333134

Entity Framework will perform updates for you on entities, not on custom results. 实体框架将为您更新实体,而不是自定义结果。 Your tblRecords holds many entities, and this is what you want to manipulate if you want Entity Framework to help. 您的tblRecords包含许多实体,如果要实体框架提供帮助,这就是您要操纵的实体。 Remove your projection (the call to Select ) and the query will return the objects directly (with too many columns, yes, but we'll cover that later). 删除投影(对Select的调用),查询将直接返回对象(列太多,是的,但是我们稍后会介绍)。

The dynamic update is performed the same way any other dynamic assignment in C# would be, since you got a normal object to work with. 由于您可以使用普通对象,因此动态更新的执行方式与C#中的其他动态分配方式相同。 Entity Framework will track the changes you make and, upon calling SaveChanges , will generate and execute the corresponding SQL queries. 实体框架将跟踪您所做的更改,并在调用SaveChanges时将生成并执行相应的SQL查询。

However , if you want to optimize and stop selecting and creating all the values in memory in the first place, even those that aren't needed, you could also perform the update from memory. 但是 ,如果您首先要优化并停止选择和创建内存中的所有值,即使不需要的值,也可以从内存中执行更新。 If you create an object of the right type by yourself and assign the right ID, you can then use the Attach() method to add it to the current context. 如果您自己创建正确类型的对象并分配正确的ID,则可以使用Attach()方法将其添加到当前上下文中。 From that point on, any changes will be recorded by Entity Framework, and when you call SaveChanges , everything should be sent to the database : 从那时起,所有更改将由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();
}

When you do a SELECT NEW ... it selects only specific fields and won't track updates for you. 当您执行SELECT NEW ...它只会选择特定的字段,不会为您跟踪更新。 I think if you change your query to be this it will work: 我认为如果您将查询更改为此,它将起作用:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM