使用EF将LINQ查询的结果分配给另一个对象

时间:2016-01-22 19:21:00

标签: c# entity-framework linq

我不确定如何在标题上写字,所以我也很感激有关该部分的任何想法,并会相应更新。

使用C#,标准控制台程序。

我有一个包含许多字段的数据库对象,可能正在更改其中的任何一个或全部。我有另一个包含新数据的相同字段的对象。 我可以一个接一个地分配它们并且它可以工作,但是如果我只是立刻做了整个事情它就不起作用。

一些代码可能更清晰。 最先工作的代码: 我需要在newStop中更新所有需要的数据。

我出去从数据库中获取数据并将其存储在findStop2中。 然后,我可以逐个浏览所有字段(此处仅显示一个字段),并将值从newStop分配给findStop2。 当我做db.SaveChanges时,一切正常。

 var findStop2 = (from s in db.stop_details 
         where s.customer_id == customer_id && s.stop_id == newStop.stop_id 
         select s)
     .First();

 //if it did not error out it found it
 findStop2.ship_date = newStop.ship_date;

但是有很多领域。为什么我不能只使用:

findStop2 = newStop;

当我执行此操作并执行SaveChanges时,不会抛出任何错误,但数据库也不会更新。

解决方案 - 最终更改的代码有效:

var findStop2 = (from s in db.stop_details where
                 s.customer_id == customer_id && s.stop_id == newStop.stop_id
                                 select s).First();
                //if it did not error out it found it
                newStop.id = findStop2.id;
                db.Entry(findStop2).CurrentValues.SetValues(newStop);

3 个答案:

答案 0 :(得分:1)

如果您的所有值都是标量,则可以使用(在EF6中):

db.Entry(findStop2).CurrentValues.SetValues(newStop);

这将正确跟踪更改和所有内容

答案 1 :(得分:0)

如果我理解你的问题,你需要将一个对象转换为另一个对象。为此,您可以写:

var myObject = db.stop_details
    .Where(sd => sd.customer_id == customer_id && sd.stop_id == newStop.stop_id)
    .Select(entity => new MyObject 
    {
        // Your properties here
    })
    .First();

或者,如果您执行此类操作很多时间(我猜您这样做),您可以使用一些映射库,例如AutoMapper。如果您正在使用mapper,那么您需要的所有内容都是编写如何将具体类型的一个对象映射到另一个对象的所有可能配置,反之亦然。在所有地方你只需要调用类似

的东西

var myObject = Mapper.Map<OutObjectType>(inputObject)

并且它。 Mapper将返回新创建的对象,并设置所有字段。

P.S。如果您决定使用Automapper,它可以很好地处理继承,接口和其他可能很难配置的东西

答案 2 :(得分:0)

您不能仅为从Entity Framework检索到的对象分配内存中对象然后将其保存到数据库的原因是您丢失了EF添加到其创建的所有对象的隐藏状态。因此,在findStop2 = newStop;之后,您的数据库上下文不再跟踪findStop2

在保存更改之前,您可以在对象state上设置directly

context.Entry(newStop).State = EntityState.Modified;

执行此操作时要小心,因为它会将数据库中的所有内容覆盖到newStop对象上的属性。 (您必须设置ID,否则它将添加另一条记录。)

修改

正如Jcl在漫画中所提到的,你需要对findStop2做一些事情,因为它也被跟踪,因此无论如何都会在数据库中创建一个单独的记录。如果您根本不需要任何属性,则无需从数据库中检索它。

您可以拨打context.Stops.Remove(findStop2),或执行与上述类似的操作:

context.Entry(findStop2).State = EntityState.Detached;