.NET MVC Core 2.2 - не может получить доступ к объекту, связанному с пользователем (внешний ключ) - PullRequest
0 голосов
/ 30 декабря 2018

Я пишу свое первое собственное приложение в MVC Core 2, и у меня возникают проблемы с доступом к Estate Entity, у которого есть внешний ключ для Пользователя.Я проверил свою базу данных, запись состояния правильно хранит userId:

Когда я пытаюсь получить context.Estates.FirstOrDefault(m => m.Id == id);, я получаю объект недвижимости, но сUser == null:

Когда я пытаюсь получить к нему доступ через:

var user = await _userManager.GetUserAsync(User);
var estate = user.Estates.FirstOrDefault(m => m.Id == id);

Я получаю нулевое исключение в списке Состояний.Кроме того, попытка сохранить его таким образом дает мне исключение:

var user = await _userManager.GetUserAsync(User);
user.Estates.Add(estate);

Однако, когда я набираю его таким образом, он правильно сохраняет данные в db:

var user = await _userManager.GetUserAsync(User);
estate.User = user;
context.Add(estate);

Понятия не имею, чтоЯ сделал неправильно здесь.Я предоставляю свой код ниже, я надеюсь, что вы можете дать мне несколько советов / советов.

Вот как я строю контекст на основе IdentityDbContext:

public class ReaContext : IdentityDbContext<User>
{
    public DbSet<Estate> Estates { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseNpgsql("Server=localhost;Port=5432;Database=rea-dev;User Id=postgres;Password=admin;");
    }

    public ReaContext(DbContextOptions<ReaContext> options)
        : base(options)
    { }

    public ReaContext()
        : base()
    { }
}

Моя модель пользователя:

public class User : IdentityUser
{
    public List<Estate> Estates { get; set; }
}

Модель недвижимости:

public class Estate
{
    [Key]
    public int Id { get; set; }
    [MaxLength(100)]
    public string City { get; set; }

    public User User { get; set; }
}

И вот как я добавляю услуги:

services.AddDbContext<ReaContext>(options => options.UseNpgsql("Server=localhost;Port=5432;Database=rea-dev;User Id=postgres;Password=admin;"));

services.AddIdentity<User, IdentityRole>().AddEntityFrameworkStores<ReaContext>();

Я также предоставляю миграции Fluent Api:

    migrationBuilder.CreateTable(
        name: "Estates",
        columns: table => new
        {
            Id = table.Column<int>(nullable: false)
                .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn),
            CreationDate = table.Column<DateTime>(nullable: false),
            UpdateDate = table.Column<DateTime>(nullable: false),
            ExpirationDate = table.Column<DateTime>(nullable: false),
            City = table.Column<string>(maxLength: 100, nullable: true),
            UserId = table.Column<string>(nullable: true)
        },
        constraints: table =>
        {
            table.PrimaryKey("PK_Estates", x => x.Id);
            table.ForeignKey(
                name: "FK_Estates_AspNetUsers_UserId",
                column: x => x.UserId,
                principalTable: "AspNetUsers",
                principalColumn: "Id",
                onDelete: ReferentialAction.Restrict);
        });

    migrationBuilder.CreateTable(
        name: "AspNetUsers",
        columns: table => new
        {
            Id = table.Column<string>(nullable: false),
            UserName = table.Column<string>(maxLength: 256, nullable: true),
            NormalizedUserName = table.Column<string>(maxLength: 256, nullable: true),
            Email = table.Column<string>(maxLength: 256, nullable: true),
            NormalizedEmail = table.Column<string>(maxLength: 256, nullable: true),
            EmailConfirmed = table.Column<bool>(nullable: false),
            PasswordHash = table.Column<string>(nullable: true),
            SecurityStamp = table.Column<string>(nullable: true),
            ConcurrencyStamp = table.Column<string>(nullable: true),
            PhoneNumber = table.Column<string>(nullable: true),
            PhoneNumberConfirmed = table.Column<bool>(nullable: false),
            TwoFactorEnabled = table.Column<bool>(nullable: false),
            LockoutEnd = table.Column<DateTimeOffset>(nullable: true),
            LockoutEnabled = table.Column<bool>(nullable: false),
            AccessFailedCount = table.Column<int>(nullable: false)
        },
        constraints: table =>
        {
            table.PrimaryKey("PK_AspNetUsers", x => x.Id);
        });

1 Ответ

0 голосов
/ 30 декабря 2018

Существуют различные способы получения связанных данных модели.

  1. Стремительная загрузка : означает, что связанные данные загружаются из базы данных как часть начального запроса.
  2. Явная загрузка : означает, что связанные данные явно загружаются из базы данных позднее.
  3. Ленивая загрузка : означает, что связаннаяданные прозрачно загружаются из базы данных при обращении к свойству навигации.

Таким образом, в вашем случае вы можете использовать Eager loading, выполнив следующие действия:

context.Estates.Include(e => e.User).FirstOrDefault(m => m.Id == id);

Для получения дополнительной информации прочитайте это: Загрузка связанных данных .


Редактировать: пример достижения Eager loading pattern на IdentityUser:

Вы можете достичь этоголибо:

  1. Инъекция UserManager<User> _userManager.
  2. Создание собственного Service, как в Service/Repository Design Pattern.

Допустим, вы выбрали первыйвариант.Тогда вы можете сделать следующее:

var user = await _userManager.Users
                 .Include(u => u.Estates)
                 .FirstOrDefaultAsync(YOUR_CONDITION);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...