繁体   English   中英

EF 4.1代码优先-如何自动更新/删除多对多联接表条目

[英]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(分离的实体)值与数据库值进行比较,找出了添加了哪些实体,以及删除了哪些实体。 这是我使用的示例代码。 作用中的实体是具有多对多关系的RelayConfigStandardContact

    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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM