Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#EF4.0 POCO-如何使用不同DbContext中的实体设置导航属性?_C#_Entity Framework 4_Domain Driven Design_Poco_Entities - Fatal编程技术网

C#EF4.0 POCO-如何使用不同DbContext中的实体设置导航属性?

C#EF4.0 POCO-如何使用不同DbContext中的实体设置导航属性?,c#,entity-framework-4,domain-driven-design,poco,entities,C#,Entity Framework 4,Domain Driven Design,Poco,Entities,我想在实体上设置外键。我在用户控件中公开了外部实体,并希望通过WinForms数据绑定进行设置 这里有一个问题-外部实体最初是从另一个存储库/DbContext加载的,因为用户控件使用自己的存储库独立填充自己 不幸的是,这不能“开箱即用”,如本例所示: var repository1 = GetRepository(); var categoryFromRepository1 = repository1.GetAll<Category>().First(); var reposit

我想在实体上设置外键。我在用户控件中公开了外部实体,并希望通过WinForms数据绑定进行设置

这里有一个问题-外部实体最初是从另一个存储库/DbContext加载的,因为用户控件使用自己的存储库独立填充自己

不幸的是,这不能“开箱即用”,如本例所示:

var repository1 = GetRepository();
var categoryFromRepository1 = repository1.GetAll<Category>().First();

var repository2 = GetRepository();
var appointmentFromRepository2 = repository2.GetNewAppointment();

appointmentFromRepository2 .Category = categoryFromRepository1;

repository2.Add(appointmentFromRepository2);

repository2.SaveChanges();
好的,repository2无法自动附加类别,因为它已附加到repository1。很好,让我们先分离:

repository1.Detach(categoryFromRepository1);
由于验证错误,它在SaveChanges()上失败-哎呀,原来repository2认为这是一个添加的条目,并试图插入。很好,为了避免这种情况,让我们也附上:

repository2.Attach(categoryFromRepository1);
这很有效!问题解决了。我现在已经将repository2实体属性设置为repository1实体,瞧

除了这个溶液吸收沼泽水。。。在整个程序中,我们有许多数据绑定的自填充用户控件,在SaveChanges()之前手动分离/重新附加所有外部实体引用是一个可怕的解决方案。此外,假设我们正在保存的存储库碰巧已经附加了对象,那么在附加()时会出现此错误:

我能想到的解决方案都没有那么好:

1) 在SaveChanges()上的通用存储库类中,扫描所有修改实体上的所有外部引用以查找数据库外上下文实体引用,动态地将它们更改为数据库内上下文实体引用(如有必要,从数据库加载)

2) 根本不设置导航属性,只设置外键ID字段(sucks0rz yo'b0x0rz)

3) 保存前手动执行这些检查(违反干燥和持久性原则)

4) 放弃与这些属性的数据绑定,手动设置属性并从主存储库加载实体(糟糕-意味着对数据库进行额外查询以获取我们已经拥有的数据)

5) 伪造用户控件,以便在需要时从给定存储库加载数据(解决方案不佳,违反了一些基本设计原则……但可行)

还有其他的想法吗

问候,


-Brendan

鉴于存在多个
DbContext
实例,似乎有多个有界上下文在起作用。具体而言,存在多种聚合,即
类别
约会
。由于存在这样的问题,最好只使用标识值实现聚合之间的引用,而不使用直接对象引用。如果
约会
仅通过ID引用
类别
,则不会出现此问题。不过,出于显示目的,您可能需要整个类别聚合。此要求可通过使用解决


查看更多信息。

感谢您的反馈。我同意这将解决眼前的问题(我测试了它),但通过采用选项(2),我们失去了此时访问类别属性(例如名称、颜色等)的好处。如果仅仅为了访问我们之前加载的类别而从数据库中重新加载它,那将是一件很遗憾的事情。它只是通过另一个DbContext加载的。最后,我们采用了(5)FYIT。单独出于阅读目的访问与出于行为或修改目的访问是有区别的。您仍然可以通过创建一个单独的读取模型来获得访问类别属性的好处,该模型将加入到类别中。这将与用于行为和持久性的模型分开。
repository2.Attach(categoryFromRepository1);
An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.