开发者

Issues with TPC inheritance with entity framework

开发者 https://www.devze.com 2023-02-16 01:17 出处:网络
I have 2 objects that I want stored separately in 2 different tables. Let\'s call the classes Foo and FooTemp.

I have 2 objects that I want stored separately in 2 different tables. Let's call the classes Foo and FooTemp.

I'm using Table Per Concrete Type (TPC) inheritance since I want class FooTemp to extend class Foo and I want the data to be stored se开发者_StackOverflow中文版parately.

The only difference between the 2 tables is FooTemp has an extra field.

I followed this guide for setting up TPC inheritance. The only difference is that I have a extra field in my derived class.

Now, here is my problem. When I add a new record to the database I get the error:

"System.ArgumentException: An item with the same key has already been added"

Why do I get this error? Is there any other way of doing inheritance and storing data in separate tables?


I believe there is a problem with TPC if you are defining autogenerated identity keys in both of your tables. Although from SQL Server perspective it isn't an issue (since the two tables are separate and can therefore have records with the same key) Entity Framework doesn't allow two objects which share the same base class to have the same key value. But this can happen if you have autogenerated keys on both tables with the same seed (for instance 1) of the identity.

I am not sure if that could be your problem. The problem I described above should not occur if you start with an empty object context, create a new Foo or FooTemp, add it to the context and save the changes.

But it would occur for instance in the following situation:

// Imagine, you know that there is a Foo with Key 1 already in the DB, or you
// could also query for that Foo to attach to the context
Foo foo = new Foo() { Key = 1 }; 
context.Foos.Attach(foo);
// Now, we have an object of type Foo with Key 1 in the object context

// Let's assume, that the table FooTemp in the DB is empty. We create the
// first FooTemp
FooTemp fooTemp = new FooTemp();
context.Foos.Add(fooTemp);

context.SaveChanges();
// If the FooTemp table has an autogenerated identity with seed 1 in the DB,
// our FooTemp gets Key 1 in the DB. Because Entity Framework accepts the
// DB changes after calling SaveChanges, our FooTemp object will now have
// the Key 1, so we have a second Foo (since FooTemp derives from Foo) with
// the same Key 1 in the same object context

Workarounds I can see:

  • Define different seeds for the autogenerated identites for the two tables which are distant enough so that it's unlikely that they ever will overlap.
  • Switch off autogenerated identites and supply your keys manually.
0

精彩评论

暂无评论...
验证码 换一张
取 消