“将子行添加到父项的子集合”v.s. “将子项添加到datacontext的子集合中”

时间:2010-12-19 04:44:22

标签: entity-framework entity-framework-4

alt text

我将比较2个场景来添加Rsvp行。你更喜欢哪一个?


方法1:将新的Rsvp对象添加到datacontext的Rsvp集合

Rsvp r = new Rsvp();
r.AttendeeName = "xport";

r.DinnerId = 1;//there will be an exception if it is set to a Dinnner object that does not exist.

entities.Rsvps.AddObject(r);

entities.SaveChanges();
  

如果我们尝试将DinnerId设置为不存在的Dinner对象,我们将收到异常。这种行为是一致和直截了当的。


方法2:将新的Rsvp对象添加到Dinner对象的Rsvps属性

Rsvp r = new Rsvp();
r.AttendeeName = "xport";

r.DinnerId = 10000;//this Dinner does not exist!

Dinner d = entities.Dinners.First(x => x.DinnerId == 1);

d.Rsvps.Add(r);

entities.SaveChanges(); 
  

Rsvp对象的外键属性DinnerId可以设置为任意数字。将此Rsvp对象添加到Dinner对象的Rsvps集合时,将以静默方式覆盖DinnerId。上面的示例显示DinnerId设置为10000,它是不存在的Dinner对象的Id。这是不可避免的行为吗?

1 个答案:

答案 0 :(得分:2)

定义方法2

为什么呢?因为如果没有晚餐 Rsvp 就不能存在。在这种关系中,晚餐是父母 - 如果我们要创建一个存储库,我们将创建一个 DinnerRepository (因为Dinner是DDD术语中的“聚合根”)

关于你的注释 - 是的,这是可以避免的行为 - 你应该做的是不要在模型上公开外键。这是您在创建/更新模型时可用的选项。

这样,必须通过实体创建/修改关系:

Rsvp r = new Rsvp();
r.AttendeeName = "xport";
r.DinnerId = 10000; // this throws a compiler error. good! we do not want people tinkering with FK's.
Dinner d = entities.Dinners.First(x => x.DinnerId == 1);
d.Rsvps.Add(r); // this is the correct way to add a RSVP
entities.SaveChanges(); 

换句话说 - 创建/修改Rsvp的唯一方法是通过Dinner - 并且不能修改FK属性。

这是有道理的。