使用 EF 将 LINQ 查询的结果分配给另一个对象
本文关键字:分配 一个对象 结果 EF LINQ 查询 使用 | 更新日期: 2023-09-27 18:31:39
我不确定标题的确切措辞,所以我也非常感谢对该部分的任何想法,并将相应地更新。
使用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);
如果所有值都是标量值,则可以使用(在 EF6 中):
db.Entry(findStop2).CurrentValues.SetValues(newStop);
这将正确跟踪更改和所有内容
理解正确,您需要将一个对象转换为另一个对象。为此,您可以编写:
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
。如果您使用的是映射器,您所需要的只是编写如何将一个具体类型的对象映射到另一个对象的所有可能配置,反之亦然。在所有地方,你只需要调用类似的东西
var myObject = Mapper.Map<OutObjectType>(inputObject)
和它。映射器将返回给您新创建的对象,并设置所有字段。
附言如果您决定使用Automapper
它与继承,接口和其他配置可能很棘手的东西一起使用
不能只将内存中对象分配给从实体框架检索的对象,然后将其保存到数据库的原因是,您将丢失 EF 添加到它创建的所有对象的隐藏状态。因此,在您的findStop2 = newStop;
之后,数据库上下文不再跟踪findStop2
。
您可以做的是在保存更改之前直接设置对象的状态。
context.Entry(newStop).State = EntityState.Modified;
执行此操作时要小心,因为它会将数据库中的所有内容覆盖为 newStop
对象上的属性。(您必须设置 ID,否则它将添加另一条记录。
编辑
正如 Jcl 在漫画中提到的,您需要对findStop2
做一些事情,因为它也被跟踪,因此无论如何都会在数据库中创建一个单独的记录。如果根本不需要其中的任何属性,则无需从数据库中检索它。
您可以调用 context.Stops.Remove(findStop2)
,也可以执行类似于上述操作的操作:
context.Entry(findStop2).State = EntityState.Detached;