Failed to save Entity Framework Inherited types

My data model implements some type-by-type inheritance (basically there is a BaseEntity type with all the basic information for my elements and an Employer that inherits from the BaseEntity element). It seems that everything is configured correctly and when using entities (through ADO.net data services or through Linq to Entities) I see the type Employer , and everything looks fine. The problem starts when I create a new Employer object and try to save it.

In a context that is not an .AddToEmployer element ( AddObject or AddToBaseEntity ).

If I use AddObject("Employer", NewEmployer) , I get an error:

Could not find EntitySet name 'DataEntities.Employer'.

If I use AddToBaseEntity(NewEmployer) , I get an error message:

It is not possible to determine the actual ordering for dependent operations. Dependencies may exist due to foreign key constraints, model requirements, or generated values.

Am I missing a step in setting up inheritance? Is there any specific way to save objects that are inherited? What am I doing wrong? I guess the main problem is that I have to have AddToEmployer , what do I need to do to expose this? It seems strange that this is not an option, since I see the Employer type on the client side and can do things like:

var NewEmployer = new Employer() - it seems, it seems that I see a beautiful type of Employer.

+4
source share
5 answers

I changed a couple of things and was able to make it work. I'm not really sure what was the main issue, but I wanted to post what I did for reference.

Recovered tables: I restored the tables, starting with only ID / Key columns and one data column.

Removed additional auto-incrementing fields: I had an auto-incrementing ID on BaseEntity and on the Employer. I deleted the auto-increment identifier in the Employer and the Employer.BaseEntityID column and the foreign key just returned to BaseEntity.BaseEntityID. (it looked like it was a criminal, but I was impressed that it was allowed)

Unfortunately, this leads to the fact that the inherited classes in the entity infrastructure cannot have navigation properties (all navigation properties must be on the base object), so inheritance will be unsuitable for our needs.

+2
source

My name is Phani and I am working on the ADO.NET Data Services team.

The ResolveName and ResolveType will help you configure the type information that the client writes to the payload sent to the server and as a tangible implementation of the payload from the server.

They help you resolve types on the client and are useful in many scenarios, a few examples:

  • The hierarchy of object types on the client is different from the server.
  • The types of objects provided by the service participate in inheritance, and you want to work with derived types on the client.

ResolveName used to change the name of the object that we put in the wire when we make a request to the server.

Consider this data model: On the server

 public class Employee { public int EmployeeID {get;set;} public string EmployeeName {get;set;} } public class Manager:Employee { public List<int> employeesWhoReportToMe {get;set;} } 

When you use the client to work with instances of type Entity Manager, when sending changes to the server, we expect the type information to be present in the payload when entities participate in inheritance.

 context.AddObject("Employees",ManagerInstance ); <-- add manager instance to the employees set. context.SaveChanges(); 

However, when the client serializes this payload, it puts "Employee" as a type name that is not expected on the server. Therefore, you must indicate the name of the client on the client,

 context.ResolveName = delegate(Type entityType){ //do what you have to do to resolve the type to the right type of the entity on the server return entityType.FullName; } 

Similarly, a type recognizer is used.

 context.ResolveType = delegate(string entitySetName){ //do what you have to do to convert the entitysetName to a type that the client understands return Type.GetType(entitySetName); } 
+7
source

Well, you only get a set of pr objects. base class, so .AddToBaseEntity is the solution as such.

But it looks like you have circular dependency in your model, so the Entity infrastructure cannot determine in which order to store.

Make sure you have foreign keys for the database on your children and update your model.

+2
source

You do not have an Employer defined as a set of entities, just like an entity type. This way you are not using AddToEntity in the context object. For one class hierarchy, there is always one entity, in this case it is the base BaseClass object.

If you want to get a set of Employer objects, you can try to manually edit the edmx file and add a new set of Employer objects, and then set the entity type Employer to this object. It should not be difficult, I have done it many times.

I am not sure if there is an even more regular solution.

+1
source

Arriving more than two years later, but in the interests of maintaining its relevance to search traffic, here I quickly worked on this in the convenience class, which we used to quickly populate our database with intermediate data.

Not sure about earlier versions, but Entity Framework 4 allows you to dump an object in context as a base object, and then the structure computes server references. So you would not use AddToInheritedObjects () (which is still deprecated), but rather the ObjectSet <> method. Add ().

Helper class example:

 public ContextHelper { … _context = ModelEntities(); public T Create<T>() where T : class { // Create a new context _context = new ModelEntities(); // Create the object using the context (can create outside of context too, FYI) T obj = _context.CreateObject<T>(); // Somewhat kludgy workaround for determining if the object is // inherited from the base object or not, and adding it to the context's // object list appropriately. if (obj is BaseObject) { _context.AddObject("BaseObjects", obj); } else { ObjectSet<T> set = _context.CreateObjectSet<T>(); set.AddObject(obj); } return obj; } … } 

Thus, if you have the following:

 class ObjectOne : BaseObject {} class ObjectTwo {} 

You can easily add objects to the context:

 ContextHelper ch = ContextHelper() ObjectOne inherited = ch.Create<ObjectOne>(); ObjectTwo toplevel = ch.Create<ObjectTwo>(); … 

Remember, of course, that ContextHelper must have a public Save () method that calls _context.SaveChanges (), or that you must have a different way of clicking an object on a storage object.

This may not be a direct answer to any question asked about inheritance, but I hope it gives people a starting point for answering specifics.

+1
source

All Articles