Проблемы с наследованием TPC со структурой сущностей - PullRequest
3 голосов
/ 11 марта 2011

У меня есть 2 объекта, которые я хочу хранить отдельно в 2 разных таблицах.Давайте назовем классы Foo и FooTemp.

Я использую наследование Table Per Concrete Type (TPC), поскольку я хочу, чтобы класс FooTemp расширял класс Foo, и я хочу, чтобы данные сохранялись отдельно.

Единственная разница между двумя таблицами состоит в том, что FooTemp имеет дополнительное поле.

Я следовал этому руководству по настройке наследования TPC .Единственная разница в том, что у меня есть дополнительное поле в моем производном классе.

Теперь моя проблема.Когда я добавляю новую запись в базу данных, я получаю сообщение об ошибке:

"System.ArgumentException: элемент с таким же ключом уже добавлен"

ПочемуЯ получаю эту ошибку?Есть ли другой способ наследования и хранения данных в отдельных таблицах?

1 Ответ

2 голосов
/ 11 марта 2011

Я полагаю, что есть проблема с TPC, если вы определяете автоматически сгенерированные идентификационные ключи в обеих ваших таблицах. Хотя с точки зрения SQL Server это не проблема (поскольку две таблицы являются отдельными и поэтому могут иметь записи с одним и тем же ключом), Entity Framework не позволяет двум объектам, имеющим общий базовый класс, иметь одинаковое значение ключа. Но это может произойти, если у вас есть автоматически сгенерированные ключи в обеих таблицах с одним и тем же начальным числом (например, 1) идентификатора.

Я не уверен, что это может быть вашей проблемой. Описанная выше проблема не должна возникать, если вы начинаете с пустого контекста объекта, создаете новый Foo или FooTemp, добавляете его в контекст и сохраняете изменения.

Но это может произойти, например, в следующей ситуации:

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

Обходные пути, которые я вижу:

  • Определите различные начальные числа для автоматически сгенерированных идентификаторов для двух таблиц, которые расположены достаточно далеко, поэтому маловероятно, что они когда-либо будут перекрываться.
  • Отключите автоматически сгенерированные идентификаторы и введите ключи вручную.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...