Unable to save Entity Framework Inherited types

ChrisHDog picture ChrisHDog · Oct 17, 2008 · Viewed 14.4k times · Source

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.

Answer

Phani Raj picture Phani Raj · Dec 15, 2008

My Name is Phani and I work on the ADO.NET Data Services team.

The ResolveName and ResolveType 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 :

  1. The type hierarchy of entities are on the client different compared to the server.
  2. Entity Types exposed by the service participate in inheritance and you want to work with derived types on the client.

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

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 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.

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

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,

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;
}

a Type resolver is used in the same way .

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);
}