#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
включен).