Один к одному и один ко многим для одного типа объекта - PullRequest
0 голосов
/ 30 мая 2018

Я пытаюсь спроектировать следующее отношение сущностей

  • Программа
  • Сборка

Программа может иметь несколько сборок.Одна из сборок будет основной сборкой.Каждая сборка принадлежит только одной программе.

Классы смоделированы следующим образом:

public class Program
{
    public int Id {get;set;}
    public virtual ProgramAssembly MainAssembly {get;set;}
    public virtual ICollection<ProgramAssembly> Assemblies {get;set;}
}

public class ProgramAssembly
{
   public int Id {get;set;}
   public virtual Program Program {get;set;}
   public int ProgramId {get;set;}
}

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

Произошла ошибка при сохранении сущностей, которые не предоставляют свойства внешнего ключа для своих отношений.Свойство EntityEntries вернет значение NULL, поскольку один объект не может быть определен как источник исключения.Обработка исключений при сохранении может быть упрощена путем предоставления свойств внешнего ключа в типах объектов.Подробности смотрите в InnerException.

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

Я попытался изменить ProgramAssembly на следующее

public class ProgramAssembly
{
    [ForeignKkey("Program")]
    public int Id {get;set;}
    public virtual Program Program {get;set;}
}

Однако, тогда я получаю этоошибка:

ProgramAssembly_Program_Source:: кратность недопустима в роли ProgramAssembly_Program_Source во взаимосвязи ProgramAssembly_Program.Поскольку зависимая роль относится к ключевым свойствам, верхняя граница кратности зависимой роли должна быть равна 1.

Я также попробовал следующий свободный подход API

modelBuilder.Entity<ProgramAssembly>()
   .HasRequired(a => a.Program)
   .WithMany(p => p.Assemblies);

public class ProgramAssembly
    {        
        public int Id { get; set; }
        public virtual Program Program { get; set; }
        [ForeignKey("Program")] //same error with or without this attribute
        public int ProgramId { get; set; }
   }

Тогда возникает ошибка:

Произошла ошибка при сохранении сущностей, которые не предоставляют свойства внешнего ключа для своих отношений.Свойство EntityEntries вернет значение NULL, поскольку один объект не может быть определен как источник исключения.Обработка исключений при сохранении может быть упрощена путем предоставления свойств внешнего ключа в типах объектов.Подробности смотрите в InnerException. 'UpdateException: невозможно определить действительный порядок для зависимых операций.Зависимости могут существовать из-за ограничений внешнего ключа, требований модели или сгенерированных в хранилище значений.

Как разрешить эту взаимосвязь без изменения подхода к добавлению атрибута IsPrimary в сборку?

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

Ответы [ 2 ]

0 голосов
/ 30 мая 2018

Приведенный ниже код удовлетворит ваше требование.

public class Program
{
    [Key]
    public int Id {get;set;}
    public virtual ICollection<ProgramAssembly> Assemblies {get;set;}
}

public class ProgramAssembly
{
   public int Id {get;set;}

   [ForeignKey("ProgramId")]
   public virtual Program Program {get;set;}
   public int ProgramId {get;set;}
   public bool IsMainProgramAssembly
}

Вы можете использовать [Required] для ProgramId, если вам это нужно, или вы можете сделать ProgramId как обнуляемый.

0 голосов
/ 30 мая 2018

Вы должны сообщить EF, как работают ваш первичный и внешний ключи.Вам необходимо добавить атрибуты, чтобы определить ваши первичные ключи [Key], определить внешние ключи и добавить атрибуты в свойства навигации, чтобы определить поле, являющееся внешним ключом.

public class Program
{
    [Key]
    public int Id {get;set;}
    public int MainAssemblyId {get;set;}
    [ForeignKey("MainAssemblyId ")]
    public virtual ProgramAssembly MainAssembly {get;set;}
    public virtual ICollection<ProgramAssembly> Assemblies {get;set;}
}

public class ProgramAssembly
{
   [Key]
   public int Id {get;set;}
   [ForeignKey("ProgramId")]
   public virtual Program Program {get;set;}
   public int ProgramId {get;set;}
}
...