[英]EF 4.1 code first - How to update/delete many to many join table entries automatically
我有2个实体,例如旅行和活动。 它们之间的关系是多对多的,因此EF自动创建了一个联接表。
实体行程属性:
-Id(PK)由数据库生成
-名称
-描述
-属性1
-Property2
-Property3
实体活动属性(此实体包含固定记录-只读-,在执行插入操作时此处未插入任何记录):
-Id(PK)由数据库生成
-名称
-描述
-成本
连接表包含两列,即上述实体的ID,它们同时是主键和外键。
我插入自动EF会自动创建联接表TripActivities并将条目成功添加到其中的条目时没有问题。 此外,条目也已成功添加到实体Trip中,并且保留了实体Activity不变。
我的问题是关于更新条目的,例如,-假设用户可以从GUI修改与行程相关的信息-因此我从该GUI获取所有信息,然后执行以下步骤来更新现有行程:
Trip trip = Context.Trips.Find(id); // Search for the appropriate trip to update from Id
trip.Name = ObtainNameFromGUI();
trip.Description = ObtainDescriptionFromGUI();
trip.Property1 = ObtainProperty1FromGUI();
trip.Property2 = ObtainProperty2FromGUI();
trip.Property3 = ObtainProperty3FromGUI();
trip.Activities = new List<Activity>();
// From the GUI user selects from a checkbox list the activities associated to the trip
// So we read its Ids and from those ids we fetch from database the activities to obtain
// the info related to each activity selected in the GUI. This is all done inside the
// below method.
List<Activity> activities = this.ObtainActivitiesSelectedFromGUI();
// If no activites selected (=null) I want EF automatically deletes the entries in the
// joined table for this trip. And of course, if there are activities selected, EF
// should update the respectives entries in the joined table for this trip with the new
// ones.
if (activites != null)
{
activities.ForEach(a =>
{
trip.Activities.Add(a);
});
}
context.Trips.Add(trip);
context.SaveChanges();<br><br>
通过这样做,我希望EF更新所有相关的实体(Activity除外,因为它具有固定的条目,必须保持不变),即Trip和联接表自动运行,但是不起作用:创建了一个新的Trip,并且其中有更多条目联接的表(唯一起作用的是实体Activity保持我想要的不变)。
如何实现呢? 我花了很多时间试图做到这一点,但没有成功...
提前致谢。
编辑:
我删除了以下行:
context.Trips.Add(trip);
现在的结果是:
-Entity Trip已正确更新,没有添加任何新记录,确定。
-实体活动保持不变,这没关系。
-Join表:当前旅行的旧记录未更新,而是为当前旅行插入了不正确的新记录。
对于遇到的类似情况,我使用了不同的方法,该方法与“分离实体”一起使用时效果很好。 我最后的结果是,通过将GUI(分离的实体)值与数据库值进行比较,找出了添加了哪些实体,以及删除了哪些实体。 这是我使用的示例代码。 作用中的实体是具有多对多关系的RelayConfig和StandardContact
public void Update(RelayConfig relayConfig, List<StandardContact> exposedContacts) {
RelayConfig dbRelayConfig = context.RelayConfigs.Include(r => r.StandardContacts)
.Where(r => r.Id == relayConfig.Id).SingleOrDefault();
context.Entry<RelayConfig> (dbRelayConfig).CurrentValues.SetValues(relayConfig);
List<StandardContact> addedExposedContacts =
exposedContacts.Where(c1 => !dbRelayConfig.StandardContacts.Any(c2 => c1.Id == c2.Id)).ToList();
List<StandardContact> deletedExposedContacts =
dbRelayConfig.StandardContacts.Where(c1 => !exposedContacts.Any(c2 => c2.Id == c1.Id)).ToList();
StandardContact dbExposedContact = null;
addedExposedContacts.ForEach(exposedContact => {
dbExposedContact = context.StandardContacts.SingleOrDefault(sc => sc.Id == exposedContact.Id);
dbRelayConfig.StandardContacts.Add(dbExposedContact);
});
deletedExposedContacts.ForEach(exposedContact => { dbRelayConfig.StandardContacts.Remove(exposedContact);});
您将使用类似这样的东西。 假设您将从UI中获得相关对象,而只是要在数据库中更新它们,则类似以下内容的东西将起作用。
context.Products.Attach(product);
context.ObjectStateManager.ChangeObjectState(product, System.Data.EntityState.Modified);
context.ObjectStateManager.ChangeObjectState(product.ProductDescription, System.Data.EntityState.Modified);
context.ObjectStateManager.ChangeObjectState(product.ProductModel, System.Data.EntityState.Modified);
context.SaveChanges();
如您在此处看到的,我们将EntityState设置为Modified,这也暗示EF也将对相关表执行更新。
请回发您的查询或在此实现中可能遇到的任何问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.