提问者:小点点

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


我有两个实体,比方说,旅行和活动。它们之间的关系是多对多的,所以EF会自动创建一个连接表。< br >

实体行程属性: -
ID (PK) 由数据库生成 -名称 -描述 -属性 1 -属性



2
-属性 3

实体活动属性(此实体包含固定记录-read only-,在执行插入时不会在此处插入任何记录):
-Id(PK)由数据库生成
-名称
-描述
-成本

连接表包含 2 列,即上述实体的 ID,它们同时是主键和外键。

我在插入条目时没有任何问题,EF会自动创建join table TripActivities并成功添加条目。此外,条目成功添加到实体行程中,实体活动保持不变。< br>

例如,我的问题是更新条目-假设用户可以从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保持不变,如我所愿)。< br>

如何实现这一点?我花了很多时间试图做到这一点,但没有成功…

提前谢谢

编辑:
我已经删除了行:
conttext. Trips.Add(旅行);

现在结果是:< br >-实体行程被正确更新,没有添加新记录,这是可以的。< br >-实体活动保持不变,这是可以的。< br >-连接表:不更新正在更新的当前行程的旧记录,而是为不正确的当前行程插入新记录。< br >


共2个答案

匿名用户

对于我所面临的类似场景,我使用了一种不同的方法,这种方法在分离的实体上工作得很好。我最终通过比较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也要对相关表执行更新。

请将您的疑问或在实施过程中可能遇到的任何问题发送回来。