EF6仅使用ID将实体添加到集合中

时间:2019-09-23 19:24:05

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

我有一个问题,我需要通过从EF读取将一个实体添加到集合中。 因为该集合所属的实体以后会添加到另一个上下文中。

示例 创建实体事件并将其保存到EFContext 1,并获得ID 1。 活动需要保存在这里,以后再添加到集合中。

已创建实体汽车,但未将其添加或保存到上下文。 汽车在几个功能之间以及用户单击按钮后传递。 汽车被传递到另一个类,并在那里添加了第二个DBContext(2)。 或可能是用户取消预订并没有保存汽车,并且该事件可以证明确实存在。

汽车具有一系列事件作为属性。 我想将Event添加到此集合中,但只能通过使用它的id来添加,因为稍后会将car添加到另一个DBContext 2中并保存。

通常我想从当前DBContext加载Event并将其添加到car实体。但是,然后两个DBContexts混合在一起。 我想要的是类似Car.Events.Add(new Event() {EventId == 1});的东西 但这想创建一个新事件,这不是我想要的。

由于是EF生成的,所以我无法访问关系表(通过EF)。

我想要的甚至是可能的吗?

1 个答案:

答案 0 :(得分:2)

有一些选项可能适合您的情况,但是在使用有限上下文时,我建议您谨慎使用,而不必接受在引用它们的每个上下文中加载实体的成本。如果一个DbContext创建了一个事件,而另一个DbContext创建了一个要绑定到该现有事件的汽车,并且知道该事件ID,则可以执行以下操作:

using (var carContext = new CarContext())
{
   var event = new Event { Id = eventId };
   carContext.Events.Attach(event);
   var car = new Car { /* ... */ };
   car.Events.Add(event);

   carContext.SaveChanges();
}

如果第二个上下文的生存期更长,例如作用于Web请求等,那么在附加事件之前,应首先使用该引用在事件的上下文中进行搜索。

Event event = carContext.Events.Local.SingleOrDefault(x => x.Id == eventId);
if (event == null)
{
   event = new Event { Id = eventId };
   carContext.Events.Attach(event);
}
// ...

如果该事件尚未保留,或者在调用此代码之前已被删除,则将在SaveChanges上引发异常。

通常,如果我绑定了一个上下文,其中Car上下文需要了解事件,但只关心将它们关联到汽车/汽车,并且只需要几列,则将简化的Event实体模型映射到仅包含事件的事件我需要的字段,然后可以在上下文中廉价地加载这些字段。例如,如果Event表有30列,但就Cars而言,我只需要Event的ID,Name和DateTime,我的CarContext会使用仅这3列而不是完整的Event实体定义来映射轻量级Event实体。这样,我的汽车环境可以安全且廉价地加载和关联该事件:

using (var carContext = new CarContext())
{
   var event = carContext.Single(x => x.Id == eventId); // Selects 3 columns from DB or can load from cache for longer-lived contexts. I get an exception here if the Event doesn't exist rather than SaveChanges.
   var car = new Car { /* ... */ };
   car.Events.Add(event);

   carContext.SaveChanges();
}

需要说明的是,除非拥有所有不可为空的字段,否则该轻量级事件不能用于创建事件行,并且即使这样,只有一个DbContext才应负责插入任何不重要的实体。对于轻量级,我通常在这些实体的名称前加上“ Lw”,即“ LwEvent”。这些实体带有注释标头,以指示它们不可用于插入。