Entity Framework 4: Table per Type inheritance problem on insert
I have simple model with a "BaseEntity" and a derived "Fund" entity. When I try to insert a new fund:
HybridModelContainer container = new HybridModelContainer();
//Create new Fund
Fund fund = new Fund();
fund.Id = Guid.NewGuid();
fund.DateCreated = DateTime.Now;
fund.Name = "Fund 1";
fund.Number = 1;
container.BaseEntities.AddObject(fund);
container.SaveChanges();
I get the following error:
"Cannot insert the value NULL into column 'Id', table 'HybridData.dbo.BaseEntities'; column does not allow nulls. INSERT fails.
The statement has been terminated."
It seems that the ID assigned to开发者_JS百科 the fund entity is not inserted into the BaseEntity table. Why not?
I did this "model first". If I design the database first, and create the model from it, everything works fine....But I need model first!
Also...why isn't there an ObjectSet
for "Funds
" in my DataContext
(i.e., container.Funds
)? Thanks in advance for your help!
I can only answer for the second part of your question: "Also...why isn't there an ObjectSet for "Funds" in my DataContext (i.e., container.Funds)?"
It's normal that the ObjectContext has only an ObjectSet of the base class in your class hierarchy. There isn't really a need for an ObjectSet of the derived classes. For adding and deleting derived objects to/from the ObjectContext you can just use the AddObject
and DeleteObject
methods of the ObjectSet<BaseEntity>
/ BaseEntities
as you already did in your example.
For querying derived objects you can leverage the OfType
method of the ObjectSet. It returns an ObjectQuery of the derived type where you can build further queries upon:
ObjectQuery<Fund> query = container.BaseEntities.OfType<Fund>();
(The first part of your question sounds like a mapping error between the storage and the conceptual model. It might have a better cif you could show the relevant parts of your edmx file.)
Edit: Possible solution to the first part of the question:
I've created your example with Model-first in VS2010 and I could reproduce your issue. The problem seems to be related to the fact that the primary key in your model isn't an Int32
but a Guid
. When you add a new Entity to the Model the designer always proposes an Int32
as primary key with StoreGeneratedPattern
set to Identity
.
If you change now the type of the key in the model designer from Int32
to Guid
but leave the StoreGeneratedPattern
unchanged being Identity
, the DDL creates a database in SQL Server with Id
set to type uniqueidentifier
but Identity specification for that column is "No".
So, when EF sends an INSERT command to the DB it "thinks" from the model definition the primary will be autogenerated in the DB and doesn't send the Guid to the DB which you have assigned in code. But the DB doesn't create the key, resulting in a NULL value for the key. Hence the error we get.
Solution: Set in the model designer for the Id
property of BaseEntity
the StoreGeneratedPattern
to None
. For me it worked then. Of course, you are responsible then to always assign a Guid to Id
before you add a new object to the ObjectSet, but that seems to be what you want anyway.
精彩评论