Ссылки внешнего ключа Entity Framework не отображаются - PullRequest
0 голосов
/ 26 мая 2018

Использование EF6 и .NET 4.6.1.Я знаю, что это в некоторой степени дубликат (я посмотрел на этот пост переполнения стека ), но выслушайте меня.У меня другой случай, и я пытался заставить его работать, используя их решения вместе с моим, но это не сработало.Так что нет, это на самом деле не дубликат.Это еще одна проблема, и я не нашел пост, который действительно помог бы мне в этой теме.

Я пытаюсь сопоставить отношения между 3 моделями;Employee, Position и Employment.Я хочу, чтобы один-ко-многим был между Employment и Position (занятость отображается на одну позицию) и один-к-одному между Employment и Employee.

public class Employment
{
    public int EmploymentID { get; set;}
    ...
    public Position Position { get; set; }
    public Employee Employee { get; set; }
}

public class Position
{
    public int PositionID { get; set;}
    ...
    [InverseProperty("Position")]
    public ICollection<Employment> Employments { get; set; }
}

public class Employee
{
    public int EmployeeID { get; set;}
    ...
    [InverseProperty("Employee")]
    public Employment Employment { get; set; }
}

Однакокогда я пытаюсь запустить это с DbContext autopping, он терпит неудачу и говорит, что не может найти отношения.Я пробовал несколько комбинаций аннотаций данных, таких как установка обратных свойств и чужого ключа ("____ ID") для некоторых из них, но не смог заставить его работать.

Я также попытался добавить виртуальные ключевые слова длянекоторые из них тоже ничего не делали.

Я бы предпочел не использовать FluentAPI, поскольку хочу, чтобы с этим автоматически работал картограф.Это не сложная проблема, достаточно для того, чтобы вручную сопоставить ее с FluentAPI (по крайней мере, на мой взгляд, это не так. Может быть, я ошибаюсь).

Какие аннотации данных мне нужны?Я посмотрел этот пост переполнения стека и различные статьи на entityframeworktutorial.net , пытаясь применить их решения к моему случаю.Но ничего не получилось.

Сбойная строка здесь:

using (EmploymentContext ctx = new EmploymentContext())
{
    Position pos = new Position()
    {
        PositionID=1,
        Name="General Manager"
    };
    ctx.Positions.Add(pos); // Failing here
    ctx.SaveChanges();
}

и сообщение об ошибке:

'Невозможно определитьосновной конец ассоциации между типами 'Ianmann.Hr.DataAccess.Employment.Employee и Ianmann.Hr.DataAccess.Employment.Employment.Основной конец этой ассоциации должен быть явно сконфигурирован с использованием API свободного взаимодействия или аннотаций данных. '

1 Ответ

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

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

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

public class Employment
{
    public int EmploymentID { get; set; }
    ...
    public Position Position { get; set; }

    [Required] // <--
    public Employee Employee { get; set; }
}

В этом случае InverseProperty является избыточным (не обязательным).

То же самое может быть достигнуто более интуитивно с помощью свободного API:

modelBuilder.Entity<Employment>()
    .HasRequired(e => e.Employee)
    .WithOptional(e => e.Employment);

Но, пожалуйста, обратите внимание, что хотя в любом случае проблема будет решена, в результате будет получен так называемый Ассоциация общего первичного ключа , где EmploymentID является как PK, так и FK до Employee.Если вам нужно отдельное свойство / столбец FK, то свободный API является обязательным, поскольку это невозможно сделать с помощью аннотаций данных:

modelBuilder.Entity<Employment>()
    .HasRequired(e => e.Employee)
    .WithOptional(e => e.Employment)
    .Map(m => m.MapKey("EmployeeID"));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...