我有2个实体,比方说,Trip和Activity。它们之间的关系是多对多的,因此EF会自动创建一个连接表。
实体旅行属性:
-Id(PK)由数据库生成
-name
-Description
-Property1
-Property2
-Property3
实体活动属性(此实体包含固定记录 - 只读 - 在执行插入时不会插入任何记录):
-Id(PK)由数据库生成
-name
-Description
-Cost
连接表包含2列,即上述实体的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更新所有相关的实体(除了活动,因为它有固定的条目,必须保持不变),即Trip和连接表自动但不起作用:创建一个新的旅程联接表中的更多条目(唯一有效的是实体活动保持不变)。
如何实现这一目标?我花了很多时间试图这样做但没有成功......
提前致谢。
编辑:
我删除了一行:
context.Trips.Add(跳闸);
现在的结果是:
-Entity Trip已正确更新,未添加任何新记录,这是好的
- 实体活动保持不变,这是好的
- 加入表:更新当前行程的旧记录不会更新,而是为当前行程插入新记录,这些记录不正确。
答案 0 :(得分:3)
我使用了一种不同的方法来处理我遇到的类似场景,这种方法适用于Detached Entities。我最后通过比较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);});
答案 1 :(得分:0)
您将使用类似的东西。假设您将从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也会对相关表执行更新。
请回复您的查询或您在此实施中可能遇到的任何问题。