Entity Framework — Элемент с тем же ключом уже добавлен. — Ошибка при попытке определить связь с внешним ключом

#.net #linq #entity-framework #linq-to-entities #entity-framework-4

#.net #linq #entity-framework #linq-to-entities #entity-framework-4

Вопрос:

У меня есть объект с отношением внешнего ключа к asp.net таблица пользователей поставщика членства.

Эта часть модели выглядит следующим образом:

альтернативный текст

Кажется, я не могу назначить связь с внешним ключом при вставке записи таблицы Users, записи, содержащей внешний ключ, в aspnet_Users таблицу. Я продолжаю получать ошибку:

Элемент с тем же ключом уже добавлен.

Код, который я использую, выглядит следующим образом:

 UserAdmin userToAdd = new UserAdmin();
...
userToAdd.aspnet_Users = membershipUser;
//line above OR line below
userToAdd.aspnet_UsersReference.EntityKey = new System.Data.EntityKey("ProjectEntities.aspnet_Users", "UserId", membershipUser.UserId);

db.AddToUsers(userToAdd);
db.SaveChanges();
  

Проблема в том, что я прошу EF добавить новую aspnet_Users запись таблицы (запись для связанной таблицы первичных ключей), когда эта запись уже существует?

Как мне присвоить значение внешнего ключа объекту, где запись первичного ключа уже существует?

Обновленный блок тестового кода:

 MembershipUser membershipUser = Membership.CreateUser("blah@blah.com", "pass", "blah@blah.com");

Entities db = new Entities();
UserAdmin newUser = new UserAdmin();
newUser.Name = "blah";
newUser.DateAdded = DateTime.Now;

Guid key = new Guid(membershipUser.ProviderUserKey.ToString());
aspnet_Users membershipUserRecord = db.aspnet_Users.Where(u => u.UserId == key).FirstOrDefault();
newUser.aspnet_Users = membershipUserRecord;
//newUser.aspnet_UsersReference.EntityKey = new System.Data.EntityKey("Entities.aspnet_Users", "UserId", membershipUserRecord.UserId);
db.ObjectStateManager.ChangeObjectState(membershipUserRecord, EntityState.Unchanged);

db.AddToUsers(newUser);
db.SaveChanges();
  

Этот код генерирует ошибку:

Элемент с тем же ключом уже добавлен.

Комментарии:

1. membershipUser Отслеживается (тем же) DataContext?

2. Да, запись MembershipUser была извлечена тем же экземпляром entity model, который используется для фиксации новой записи пользователя.

Ответ №1:

Хорошо, я разобрался с этим. Как обычно, это просто я допустил ошибку и не уловил ее сразу, потому что искал не в том месте.

Проблема была связана с моим наследованием таблицы и конфигурацией на уровне базы данных. У меня было поле внешнего ключа дочерней таблицы (UserAdmin), определенное как идентификатор, которое затем отображалось в моей модели как StoreGeneratedPattern = Identity. Это вызывало ошибку «Элемент с тем же ключом уже добавлен», когда EF пытался распространить родительский первичный ключ на дочернее поле внешнего ключа.

Как только я удалил спецификацию идентификации из таблицы UserAdmins, проблема исчезла.

Проблема решена.

Ответ №2:

Да, это именно та проблема. Как вы получили объект MembershipUser? Если вы не получили его из текущего ObjectContext, EF считает, что это новый, и пытается вставить его в таблицу aspnet_users.

Попробуйте использовать этот код после добавления пользователя в ObjectSet:

 // db is ObjectContext instance
db.ObjectStateManager.ChangeObjectState(membershipUser, EntityState.Unchanged);
  

Вероятно, есть несколько других способов добиться того же результата, но у меня это работает.

Комментарии:

1. Я пытался использовать ChangeObjectState(), но безрезультатно, по-прежнему получая ошибку «Элемент с тем же ключом уже добавлен». Я добавил внешний вид моего тестового кода в исходное сообщение.

2. Я проверил ваш код, и он должен работать. Более того, когда вы выбираете aspnet user с помощью EF, вам не нужно устанавливать его состояние — оно уже находится в неизмененном состоянии. Таблица Users пуста? Автоматически ли генерируется идентификатор пользователя в таблице Users? Если вы используете SQL Server и у вас установлен SQL Profiler, вы можете проверить, какие команды SQL выполняются.

3. Я запустил профиль в базе данных, и, похоже, я не вижу никаких инструкций insert после того, как поставщик членства делает это для членства. CreateUser(). Вызов SaveChanges(), похоже, вообще не выполняет никаких инструкций insert или update для базы данных.

4. Кажется, что ошибка возникает в коллекциях объектов до того, как изменения будут отправлены в базу данных: [Исключение ArgumentException: элемент с тем же ключом уже добавлен.] Система. Коллекции. Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add) 12753120 System.Data.Mapping. Обновить. Внутренний. UpdateCommandOrderer. AddServerGenDependencies() 232 [Исключение UpdateException: значение, общее для объектов или ассоциаций, генерируется более чем в одном расположении. Проверьте, что сопоставление не разбивает EntityKey на несколько столбцов, сгенерированных хранилищем.]