ASP.NET Ядро 5 и структура сущностей : проблемы навигации на основе конвенций

#c# #asp.net-core #entity-framework-core

Вопрос:

У меня есть ASP.NET Приложение MVC, которое использует Entity Framework с навигацией на основе соглашений, и оно отлично работает. Я решил поэкспериментировать, переехав в ASP.NET Ядро 5 с ядром Entity Framework v5.0.6. Ну не просто, какой медведь, так как соглашения для одного ко многим нарушаются. Боюсь попробовать мои многие-ко-многим!

Я расширил IdentityUser , чтобы включить свойство навигации List<BookedDates> :

 public class ApplicationUser : IdentityUser
{
        public int skillLevel { get; set; }
        public int timesCaptain { get; set; }
        public int bFreezeDB { get; set; }
        public string memberName { get; set; }
        public virtual List<BookedDates> bookedDates { get; set; }
        public virtual List<Match> Matches { get; set; }

        public ApplicationUser()
        {
            bFreezeDB = 0;
        }
}
 

Теперь у пользователя может быть много BookDates :

 public class BookedDates
{
    public int id { get; set; }
    public int month { get; set; }
    
    public virtual ApplicationUser user { get; set; }
    public string status { get; set; }
}
 

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

  migrationBuilder.CreateTable(
            name: "statusforDays",
            columns: table => new
            {
                id = table.Column<int>(type: "int", nullable: false)
                    .Annotation("SqlServer:Identity", "1, 1"),
                Name = table.Column<string>(type: "nvarchar(max)", nullable: true),
                month = table.Column<int>(type: "int", nullable: false),
                status = table.Column<string>(type: "nvarchar(max)", nullable: true),
                ApplicationUserId = table.Column<string>(type: "nvarchar(450)", nullable: true)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_statusforDays", x => x.id);
                table.ForeignKey(
                    name: "FK_statusforDays_AspNetUsers_ApplicationUserId",
                    column: x => x.ApplicationUserId,
                    principalTable: "AspNetUsers",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Restrict);
            });
 

Затем в своем контроллере я делаю следующий вызов:

 ApplicationUser user = _db.Users
                          .Include(u => u.bookedDates)
                          .Where(u => u.Email == email)
                          .SingleOrDefault();
 

Я получаю эту ошибку:

«Microsoft.Data.SqlClient.SQLException» в Microsoft.EntityFrameworkCore.Relational.dll
В Microsoft произошло исключение типа «Microsoft.Data.SqlClient.SQLException».EntityFrameworkCore.Реляционный.dll, но не был обработан в коде пользователя
Недопустимое имя столбца «Идентификатор пользователя».

Откуда это userid берется? Я знаю, что, вероятно, смогу использовать Fluent и создать связь, но я думал, что EF Core 5 должен был обрабатывать простую навигацию на основе соглашений намного лучше, чем v3

Ответ №1:

Я всегда предлагаю подход FluentAPI, потому что это дает вам больше контроля над отношениями.

В вашем BookedDates классе у вас есть свойство навигации: public virtual ApplicationUser user { get; set; } . По соглашению, EF Core выполняет поиск по имени свойства, за которым следует Id столбец внешнего ключа: userId как показано в ошибке.

Переименуйте свойство как public virtual ApplicationUser ApplicationUser { get; set; } , и вместо этого соглашение будет искать ApplicationUserId поле в таблице userId .

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

1. Затем отметьте ответ как решение, пожалуйста. Кто-то проголосовал против ответа без комментариев по причине.