Entity Framework 4.1 Codefirst: ошибка «Заданные ограничения множественности» при удалении дочерних элементов «один ко многим» - PullRequest
8 голосов
/ 29 июля 2011

У меня есть следующие классы в Entity Framework 4.1 (классы были сокращены для обеспечения читабельности кода)

public class MetaInformation
{
    public int Id { get; set; }
    public virtual MetaInformationObject RelatedTo { get; set; }
}

public abstract class MetaInformationObject
{
    public int Id { get; set; }
    public virtual List<MetaInformation> MetaInformations { get; set; }
}

[Table("Hardwares")]
public class Hardware : MetaInformationObject
{
    [MaxLength(100)]
    public string Name { get; set; }
}

public class Inventory
{
    public int Id { get; set; }
    public virtual List<Machine> Machines { get; set; }
}

public class Machine : Hardware
{
    public Inventory Inventory { get; set; }
}

 protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Isis.Business.Base.MetaInformationObject>()
        .HasMany<Isis.Business.Base.MetaInformation>(mi => mi.MetaInformations).WithRequired(mi => mi.RelatedTo).WillCascadeOnDelete(true);
    modelBuilder.Entity<Isis.Business.Inventory.Inventory>()
            .HasMany<Isis.Business.Inventory.Machine>(i => i.Machines).WithRequired(m => m.Inventory).WillCascadeOnDelete(true);

    base.OnModelCreating(modelBuilder);
}

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

public void UpdateMachine(Inventory i, Machine m)
{
    DataContext.Dao.Db.Inventories.Attach(i);
    if (!i.Machines.Exists(InnerHardware => InnerHardware.SerialNumber == m.SerialNumber)) {
        i.Machines.Add(m);
    } else {
        var workingMachine = i.Machines.First(Machine => Machine.SerialNumber == m.SerialNumber);
        Dao.Db.Machines.Attach(workingMachine);
        if (workingMachine.MetaInformations != null && workingMachine.MetaInformations.Count > 0) {
            workingMachine.MetaInformations.Clear();
            //workingMachine.MetaInformations.ForEach(mi => { Dao.Db.MetaInformations.Attach(mi); Dao.Db.MetaInformations.Remove(mi); }); // tried this to, with variations
        }
        workingMachine.MetaInformations = m.MetaInformations;
    }
    DataContext.Dao.Db.SaveChanges();
}

И затем выдается следующее исключение DbUpdateException:

Отношение из 'MetaInformationObject_MetaInformations' AssociationSet находится в состоянии «Удалено». Учитывая множественность ограничения, соответствующие 'MetaInformationObject_MetaInformations_Target' также должна быть в «Удалено».

Я попытался ответить на некоторые вопросы здесь на SO, чтобы решить эту проблему, особенно пытаясь прочитать этот и ссылку , приведенную в ответе (вот почему существует прямая ссылка с MetaInformation до MetaInformationObject), но я не могу понять, что случилось.

Ответы [ 2 ]

16 голосов
/ 29 июля 2011

Каскадное удаление здесь вам не поможет.Каскадное удаление работает, только если вы удаляете родительский объект (MetaInformationObject).Проблема здесь в том, что вызов Clear для коллекции связанных объектов не удаляет их.Он только удаляет отношение (= он установит внешний ключ в MetaInformation на ноль), но это не разрешено вашими ограничениями отображения (вы определили отношение как требуется).Есть несколько способов избежать этого:

  • Итерация по всем связанным MetaInformation s и удаление каждого из них
  • Рефакторинг вашей модели для определения идентифицирующего отношения .После этого Clear не только разорвет отношение, но и пометит связанный объект как удаленный.
0 голосов
/ 05 января 2016

Повторение приведенного выше комментария, приведенного ниже кода решит вашу проблему

DataContext.Dao.Db.MetaInformations.RemoveRange (workingMachine.MetaInformations);

...