Entity Framework и внешние ключи той же таблицы

#c# #sql #entity-framework

#c# #sql #entity-framework

Вопрос:

Чтобы описать, что я хочу: предположим, у меня есть таблица User в SQL Server, которая содержит поле первичного ключа и два поля, которые ссылаются на ту же таблицу с использованием внешних ключей.

 CREATE TABLE [User] (
    ID INT IDENTITY(1, 1) NOT NULL,
    -- other properties omitted for brevity
    CreatedByUserID INT NOT NULL,
    LastModifiedByUserID INT NOT NULL,
    CONSTRAINT PK_User PRIMARY KEY (ID),
    CONSTRAINT FK_User_CreatedByUser FOREIGN KEY (CreatedByUserID) REFERENCES User 
(ID),
    CONSTRAINT FK_User_LastModifiedByUser FOREIGN KEY (LastModifiedByUserID) REFERENCES User (ID),
)
  

Я могу настроить пользователя «root», выполнив следующий SQL:

 INSERT [User] (CreatedByUserID, LastModifiedByUserID) VALUES (1, 1)
  

SQL Server не выдает никаких ошибок.

Теперь, если я попытаюсь сначала создать ту же таблицу, используя код Entity Framework, я получу смешанные результаты:

 public class User
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int ID { get; set; }

    [ForeignKey(nameof(CreatedByUser))]
    public int CreatedByUserID { get; set; }

    //[ForeignKey(nameof(ModifiedByUser))]
    //public int ModifiedByUserID { get; set; }

    public virtual User CreatedByUser { get; set; }

    //public virtual User ModifiedByUser { get; set; }
}
  

Это работает, как показано, но когда я раскомментирую строки ModifiedByUser *, я получаю множество ошибок «Множественность недопустима в роли».

Я пытался преобразовать свой класс, управляемый аннотациями, в конфигурацию в стиле fluent, но при запуске мне не везет Add-Migration : всегда возникает какая-то ошибка, возникающая при некоторой комбинации методов настройки, и, похоже, я никогда не могу указать CreatedByUserID или LastModifiedByUserID имена столбцов.

 user.HasRequired(x => x.CreatedBy);
    //.WithRequiredPrincipal();
user.HasRequired(x => x.LastModifiedBy);
    //.WithRequiredPrincipal();
  

Пытаюсь ли я сделать что-то, что запрещено Entity Framework? Или я пропустил одну или две строки конфигурации? Как я могу использовать EF для воссоздания структуры таблицы, показанной в верхней части этого поста?

РЕДАКТИРОВАТЬ: Тот же шаблон отлично работает для ряда других объектов в модели: например, WorkItem может иметь оба CreatedByUser и ModifiedByUser ; проблема, похоже, возникает только тогда, когда внешние ключи ссылаются на объект того же типа, что и их окружающий тип.

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

1. Это невозможно в EF6 (не уверен насчет ядра EF), потому что оно игнорирует явные значения PK для автоматически сгенерированных ключей. Вам лучше изменить дизайн, разрешив null CreatedByUserId — «стандартный» подход для решения таких проблем.

2. Я использую EF 6. Разрешение обнулять только один (или даже оба) из двух внешних ключей для меня не решает проблему. Я пробовал использовать аннотации, а также fluent API. Я получаю ту же ошибку, что «Поскольку свойства зависимой роли не являются свойствами ключа, верхняя граница кратности зависимой роли должна быть ‘*'».

3. Вы меня неправильно поняли. Модель может быть легко настроена — user.HasRequired(x => x.CreatedBy).WithMany(); user.HasRequired(x => x.LastModifiedBy).WithMany(); . Но вы не сможете создать, User используя CreatedByUserId тот же User идентификатор, что и в примере SQL (за исключением случаев, когда вы используете SQL напрямую и у вас identity_insert включен).