Как сохранить дочерние отношения в 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 за один раз.

Я могу дать более конкретный совет, если вы покажете больше кода.

Другие вопросы по тегам