Как сохранить дочерние отношения в Entity Framework
У меня есть проект Entity Framework v1. У меня есть две сущности (роли и разрешения), которые имеют отношения многие ко многим друг с другом. Я передаю объект для сохранения (посредством вызова WCF, я не создаю его из контекста самостоятельно), у которого есть новые записи в отношении многие ко многим.
Я использую "context.ApplyPropertyChanges", чтобы обновить запись с новыми свойствами. Я знаю, что это не обновляет отношения, хотя. Я пытаюсь либо сделать ChildCollection.Add (relatedObject); или ChildCollection.Attach (relatedObject).
Когда я использую метод "Добавить", я получаю сообщение об ошибке: объект не может быть добавлен в ObjectStateManager, потому что у него уже есть EntityKey. Используйте ObjectContext.Attach, чтобы прикрепить объект, который имеет существующий ключ.
Когда я использую метод Attach, я получаю сообщение об ошибке: объект не может быть добавлен в ObjectStateManager, потому что у него уже есть EntityKey. Используйте ObjectContext.Attach, чтобы прикрепить объект, который имеет существующий ключ.
Я очень расстроен и думаю, что слышу, как Entity Framework смеется надо мной.
Кто-нибудь знает, как я могу решить эту проблему?
MyRole x = context.Roles.FirstOrDefault(a => a.RoleId == this.RoleId);
context.ApplyPropertyChanges("Roles", this);
foreach (MyPermission p in this.Permissions)
{
x.Permissions.Add(p);
// ^ or v
x.Permissions.Attach(p);
}
context.SaveChanges();
Благодарю.
3 ответа
Вот это да. После 20 или около того часов подряд по этой проблеме я начинаю ненавидеть Entity Framework. Вот код, который, кажется, работает в настоящее время. Буду признателен за любые советы о том, как сделать это более упорядоченным.
Я переделал службу WCF, чтобы был только один контекст данных. Спасибо, Крейг.
Затем мне пришлось изменить код на следующее:
MyRole x = context.Roles.FirstOrDefault(a => a.RoleId == this.RoleId);
if (x == null) // inserting
{
MyApplication t = this.Application;
this.Application = null;
context.Attach(t);
this.Application = t;
}
else // updating
{
context.ApplyPropertyChanges("Roles", this);
x.Permissions.Load();
IEnumerable<Guid> oldPerms = x.Permissions.Select(y => y.PermissionId);
List<MyPermission> newPerms = this.Permissions.Where(y => !oldPerms.Contains(y.PermissionId)).ToList();
IEnumerable<Guid> curPerms = this.Permissions.Select(y => y.PermissionId);
List<MyPermission> deletedPerms = x.Permissions.Where(y => !curPerms.Contains(y.PermissionId)).ToList();
// new
foreach (MyPermission p in newPerms)
{
x.Permissions.Add(context.Permissions.First(z => z.PermissionId == p.PermissionId));
}
// deleted
foreach (MyPermission p in deletedPerms)
{
x.Permissions.Remove(context.Permissions.First(z => z.PermissionId == p.PermissionId));
}
}
Я подозреваю, что вы получаете ошибки, потому что ObjectContext думает, что вы пытаетесь добавить новый объект, но обнаруживает, что он уже имеет EntityKey. Я использую метод AttachTo ObjectContext, чтобы присоединить мои уже существующие сущности к их EntitySet. У меня были результаты генерации моих сущностей из заглушек или попадания в базу данных. Таким образом, когда вы добавляете сущность к свойству навигации на вашей сущности, ObjectContext находит сущность в ее EntitySet и знает, что это существующая сущность, а не новая. Я не знаю, понятно ли это. Я мог бы опубликовать код, если это поможет. Как сказал г-н Стунц в своем ответе, размещение вашего кода поможет.
Вы используете несколько ObjectContexts одновременно (переменная context
и везде this
пришли из). Не делай этого. Это только усложнит вам жизнь. Используйте один ObjectContext за один раз.
Я могу дать более конкретный совет, если вы покажете больше кода.