阻止实体框架插入导航属性的值
我正在使用 Entity Framework 4.0 开发 WPF 应用程序。当我尝试保存对象时,出现主键异常,但主键是自动增量字段,我无法理解异常的原因。
因此,在尝试了这个和那个,并进行了一些调试和使用 SQL 分析器之后,我发现在插入对象之前,必须在父表中插入一条记录,因为我设置了该对象的导航属性。
所以关键是如果尝试插入 Employee 对象并将其部门设置为 Employee.Department = deptObject,则将在部门对象上插入一条新记录。
请建议我以某种方式将导航属性对象插入到数据库中,任何属性或任何方法,任何东西。
谢谢
I am working on a WPF application using Entity Framework 4.0. When I tried to save the object, I got a primary key exception, but the primary key is an AutoIncremented field and I cannot understand the reason for the exception.
So after trying this and that, and a little debugging and using the SQL profiler, I found out that prior to inserting my object, a record must be inserted in the parent table, as I set the navigation property of that object.
So the crux is if an attempt to insert Employee object and set its department as Employee.Department = deptObject, then a new record is set to be inserted on department object.
Kindly suggest me someway by which navigational property objects won't be inserted in the database, any property or any method, Anything.
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果您错误地使用分离实体,这就是 EF 的工作方式。我想您正在使用类似的内容:
此代码准备了员工实体,添加了对现有部门的引用并将新员工保存到数据库中。问题出在哪里?问题是
AddObject
不仅添加员工,还添加整个对象图。这就是 EF 的工作原理 - 您不能拥有其中部分对象连接到上下文而部分不连接的对象图。AddObject
将图中的每个对象添加为新对象(新对象 = 插入数据库)。因此,您必须更改操作顺序或手动修复实体的状态,以便您的上下文知道该部门已经存在。第一个解决方案 - 使用相同的上下文来加载部门和保存员工:
第二个解决方案 - 分别将实体连接到上下文,然后在实体之间进行引用:
第三个解决方案 - 手动更正部门的状态,以便上下文不会再次插入它:
This is the way how EF works if you incorrectly use detached entities. I suppose you are using something like this:
This code prepared employee entity, added reference to existing department and saved new employee to the database. Where is the problem? The problem is that
AddObject
doesn't add only employee but whole object graph. That is how EF works - you cannot have object graph where part of objects are connected to context and part of not.AddObject
adds every object in the graph as a new one (new one = insert in database). So you must either change sequence of your operations or fix state of entities manually so that your context knows that department already exists.First solution - use the same context for loading department and saving employee:
Second solution - connect entities to the context separately and after that make reference between entities:
Third solution - correct state of the department manually so that context doesn't insert it again:
除了 Ladislavs 很好的答案中已经提供的 3 个解决方案之外,我还想添加第四个解决方案。事实上,这是 Naor 简短回答的详细版本。我正在使用实体框架版本 6。
将部门 ID 分配给员工而不是部门对象
除了模型中的导航属性之外,我倾向于拥有“外键值”属性类。
因此,在
Employee
类上,我有一个Department
属性,还有一个 int 类型的DepartmentId
(如果可能的话,请使 int 为空) >Employee 没有Department
):您现在可以做的就是设置
DepartmentId
:因此,只需
设置:
或
现在,当对添加的员工调用
SaveChanges
时,只会保存该员工,不会创建新部门。但由于分配了部门 ID,因此从Employee
到Department
的引用设置正确。更多信息
我通常仅在读取/处理员工时才会访问
Employee
类的Department
对象。创建或更新员工时,我将使用
Employee
类的DepartmentId
属性进行分配。不分配给
Employee
的Department
属性有一个缺点:它可能会使调试更加困难,因为在调用SaveChanges
并重新读取员工将无法查看或使用Employee
的Department
对象。修复 EF6 中的实体状态信息
这指的是 Ladislavs 解决方案 3。
在 EF6 中,它是这样完成的:
I would like to add a 4th solution to in addition to the 3 solutions already provided in Ladislavs great answer. In facts its a detailed version of the short answer from Naor. I am working with entity framework version 6.
Assign the deparment id to the employee instead of department object
I tend to have a "foreign key value" property in addition to the navigation property in my model classes.
So on the
Employee
class I have aDepartment
property and also anDepartmentId
of type int (make the int nullable if its possible that anEmployee
has noDepartment
):Would you could do now is just setting the
DepartmentId
:So instead of:
just set:
or
Now when calling
SaveChanges
on the added employee, only the employee gets saved and no new department is created. But the reference fromEmployee
toDepartment
is set correctly because of the assigned department id.More info
I usually would access the
Department
object of theEmployee
class only when reading / processing employees.When creating or updating employees, I would use the
DepartmentId
property of theEmployee
class to assign to.Not assigning to the
Department
property of theEmployee
has one downside: It could make debugging more difficult, because before callingSaveChanges
and re-reading the employees it would not be possible to see or use theDepartment
object of theEmployee
.Fixing entity state info in EF6
This refers to Ladislavs solution number 3.
With EF6 it is done that way:
当您将部门设置为员工时 - 我认为您应该验证该部门是从数据库检索的并且它附加了实体。
另外,您可以输入部门的 id(外键属性)来代替设置部门导航属性。
When you set the department to employee - I think that you should verify the department was retrieved from the db and it attached entity.
In addition, you can put the id of deprtment (the foreign key property) instead of set the department navigation property.
就我而言,我有从不同上下文(不同数据库)手动填充的集合。为了防止我的主上下文尝试保存这些集合,我最终
向属性定义添加了注释。
In my case I had collections that were manually populated from a different context (different database). In order to prevent my main context from trying to save these collections I ended up adding
annotations to the property definitions.