无法保存实体框架继承类型
我在我的数据模型中实现了一些表类型继承(基本上有一个 BaseEntity
类型,其中包含我的项目的所有基本信息和一个 Employer
类型,该类型继承自BaseEntity
项)。 一切似乎都设置正确,并且在使用实体时(通过 ADO.net 数据服务或通过 Linq to Entities),我可以看到 Employer
类型,并且一切似乎都很好。 当我创建一个新的 Employer
实体并尝试保存它时,问题就开始了。
在似乎不是 .AddToEmployer
项的上下文中(仅限 AddObject
或 AddToBaseEntity
)。
如果我使用 AddObject("Employer", NewEmployer)
我收到以下错误消息:
找不到 EntitySet 名称“DataEntities.Employer”。
如果我使用 AddToBaseEntity(NewEmployer)
我会收到以下错误消息:
无法确定相关操作的有效顺序。 由于外键约束、模型要求或存储生成的值,可能会存在依赖关系。
我是否错过了设置继承的步骤? 有没有一些特定的方法来保存继承的对象? 我究竟做错了什么? 我认为基本问题是我应该有一个 AddToEmployer
,我需要做什么才能暴露它? 奇怪的是,这不是一个选项,因为我可以在客户端看到雇主类型,并且可以执行以下操作:
var NewEmployer = new Employer()
- 这似乎表明我可以看到雇主类型很好。
I have implemented some table-per-type inheritance in my data model (basically have a BaseEntity
type with all the base information for my items and a Employer
type that inherits from the BaseEntity
item). Everything appears to be set up correctly and when using the Entities (either via ADO.net Data Services or via Linq to Entities) I can see the Employer
type and things appear to be fine. The issue starts when I create a new Employer
entity and attempt to save it.
On the context that doesn't appear to be an .AddToEmployer
item (only and AddObject
or AddToBaseEntity
).
If I use AddObject("Employer", NewEmployer)
I get and error message of:
The EntitySet name 'DataEntities.Employer' could not be found.
If I use AddToBaseEntity(NewEmployer)
I get an error message of:
Unable to determine a valid ordering for dependent operations. Dependencies may exist due to foreign key constraints, model requirements orstore generated values.
Have I missed a step in setting up the inheritance? Is there some specific way to save objects that are inherited? What am I doing wrong? I assume that the basic issue is that I should have an AddToEmployer
, what do I need to do to get that exposed? It seems odd that it is not an option since I can see the Employer type on the client side and can do things such as:
var NewEmployer = new Employer()
- which seems to suggest that I can see the Employer type fine.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我叫 Phani,在 ADO.NET 数据服务团队工作。
ResolveName
和ResolveType
方法用于帮助您自定义客户端在发送到服务器的有效负载中写入的类型信息以及如何具体化来自服务器的响应有效负载。它们帮助您解析客户端上的类型,并且在许多场景中都很有用,例如:
ResolveName
用于更改我们在向服务器发出请求时放置在线路上的实体的名称。考虑这个数据模型:
在服务器上
当您使用客户端来处理 Manager 实体类型的实例时,
将更改提交到服务器后,当实体参与继承时,我们期望类型信息出现在有效负载中。
但是,当客户端序列化此有效负载时,它会输入“Employee”作为类型名称
这不是服务器所期望的。
因此,您必须在客户端上提供名称解析器,
以相同的方式使用类型解析器。
My Name is Phani and I work on the ADO.NET Data Services team.
The
ResolveName
andResolveType
methods are to help you customize the type information that the client writes in the payload sent to the server and how the response payload from the server is materialized .They help you resolve types on the client and are useful in many scenarios , a couple of examples are :
ResolveName
is used to change the name of the entity that we put on the wire when making a request to the server.Consider this data model :
On Server
When you use the client to work with instances of the Manager Entity Type ,
upon submitting the changes to the server, we expect type information to be present in the payload when entities participate in inheritance.
However, when the client serializes this payload, it puts in "Employee" as the type name
which is not what is expected on the server.
Hence you have to provide a name resolver on the client,
a Type resolver is used in the same way .
那么你只能得到一个实体集 pr。 基类所以 .AddToBaseEntity 就是这样的解决方案。
但听起来您的模型中有循环依赖关系,因此实体框架无法确定按哪个顺序保存。
检查派生实体上的基本实体是否具有外键并更新模型。
Well you only get an entity set pr. base class so .AddToBaseEntity is the solution as such.
But it sounds like you have a circular dependency in your model, so that the Entity framework cannot figure out in which order to save.
Check that you have foreign keys to the baseentity on your derived entities and update your model.
我改变了一些事情并且能够让它发挥作用。 我不太确定基本问题是什么,但想发布我所做的事情以供参考。
重建表:我从 ID/Key 列和单个数据列开始重建表。
删除了额外的自动递增字段:我在 BaseEntity 和 Employer 上有一个自动递增 ID。 我删除了 Employer 上的自动递增 ID,只将 Employer.BaseEntityID 列和外键返回到 BaseEntity.BaseEntityID。 (这似乎是罪魁祸首,但我的印象是这是允许的)
不幸的是,这导致了实体框架中的继承类不能具有导航属性的问题(所有导航属性必须位于基本实体上),因此继承将被证明无法满足我们的需求。
I changed a couple of things and was able to get this to work. I am not particularly sure what was the base issue, but wanted to post what I did do for reference.
Rebuilt Tables: I rebuilt the tables starting with just the ID/Key columns and a single data column.
Removed extra auto incrementing fields: I had an auto-incrementing ID on the BaseEntity and on the Employer. I removed the auto-incrementing ID on the Employer and just had the Employer.BaseEntityID column and the foreign key back to BaseEntity.BaseEntityID. (this seems to have been the culprit, but I was under the impression this was permitted)
Unfortunately this then lead to the issue that enherited classes in the entity framework cannot have navigation properties (all navigation properties must be on the base entity) so inheritance is going to prove to be non-usable for our needs.
您没有将雇主定义为实体集,就像实体类型一样。 这就是您在上下文对象中缺少 AddToEntity 的方式。 一个类层次结构总是有一个实体集,在本例中它是 BaseClass 实体集。
如果您想获取实体集“雇主”,您可以尝试手动编辑 edmx 文件并添加新的实体集“雇主”,然后将实体类型“雇主”设置为属于该实体集。 应该不难,我已经做过很多次了。
我不确定是否有一些更常规的解决方案。
You don't have Employer defined as entity set, just like entity type. That is way you are missing AddToEntity in the context object. There is always one entity set for one class hierarchy, in this case it is BaseClass entity set.
If you want to get entity set 'Employer' you can try to manually edit edmx file and to add new entity set 'Employer', and then set entity type 'Employer' to belong to that entity set. It shouldn't be hard, I've done it a lot of times.
I'm not sure if there is some more regular solution.
两年多后推出,但为了保持其与搜索流量的相关性,我在一个便利类中快速解决了这个问题,我们用它来快速填充暂存数据的数据库。
不确定早期版本,但实体框架 4 允许您将对象作为基础对象转储到上下文中,然后框架计算出服务器端引用。 因此,您不会使用 AddToInheritedObjects() (无论如何已弃用),而是使用 ObjectSet<>.Add() 方法。
这是一个帮助器类示例:
因此,假设您有以下内容:
您可以轻松地将实体添加到上下文中:
当然,请记住 ContextHelper 应该有一个调用 _context.SaveChanges() 的公共 Save() 方法 - 或者您应该有一些其他方法将对象更改推送到数据存储。
这可能不是对任何有关继承的特定问题的直接回答,但希望为人们提供一个回答细节的起点。
Coming over two years later, but in the interest of keeping it relevant for the search traffic, here's a way I worked around this quickly in a convenience class that we were using to quickly populate our database with staging data.
Not sure about earlier versions, but Entity Framework 4 lets you dump the object into the context as a base object, and then the framework figures out the server-side references. Thus, you wouldn't used AddToInheritedObjects() (which is deprecated anyway) but rather the ObjectSet<>.Add() method.
Here's a helper class example:
Thus, assuming you have the following:
You could easily add entities to the context:
Remembering, of course, that ContextHelper should have a public Save() method which calls _context.SaveChanges()- or that you should have some other way of pushing the object changes up to the datastore.
This might not be a direct response to any given question about inheritance, but hopefully gives people a starting point to answer specifics.