Невозможно вывести объект внешнего ключа в ядре 2.2, даже если записи данных кажутся правильными - PullRequest
0 голосов
/ 09 июля 2019

У меня есть сложный тип (общежитие), который имеет поле адреса (тип адреса), но когда я отлаживаю функцию в общежитии, он имеет поле адреса = null, хотя при открытии проводника базы данных внешний ключ addressID заполнено правильно.

Я убедился, что SQL правильный, но сейчас не уверен, где искать ошибку

dbcontext выглядит следующим образом, и у меня есть идея, что это может быть там, где проблема

namespace OptimalHousing.Models
{
    public class OptimalHousingContext : DbContext
    {
        public OptimalHousingContext (DbContextOptions<OptimalHousingContext> options)
            : base(options)
        {
        }

        public DbSet<OptimalHousing.Models.Dorm> Dorm { get; set; }
        public DbSet<OptimalHousing.Models.Address> addresses { get; set; }
    }
}

Общежитие sql

CREATE TABLE [dbo].[Dorm] (
    [id]        INT            IDENTITY (1, 1) NOT NULL,
    [addressid] INT            NULL,
    [dormName]  NVARCHAR (MAX) NULL,
    [dormUrl]   NVARCHAR (MAX) NULL,
    CONSTRAINT [PK_Dorm] PRIMARY KEY CLUSTERED ([id] ASC),
    CONSTRAINT [FK_Dorm_Address_addressid] FOREIGN KEY ([addressid]) REFERENCES [dbo].[Addresses] ([id])
);


GO
CREATE NONCLUSTERED INDEX [IX_Dorm_addressid]
    ON [dbo].[Dorm]([addressid] ASC);

Адреса sql

CREATE TABLE [dbo].[addresses] (
    [id]           INT            IDENTITY (1, 1) NOT NULL,
    [street]       NVARCHAR (MAX) NULL,
    [streetNumber] INT            NOT NULL,
    [zipCode]      INT            NOT NULL,
    [longitude]    NVARCHAR (MAX) NULL,
    [latitude]     NVARCHAR (MAX) NULL,
    CONSTRAINT [PK_addresses] PRIMARY KEY CLUSTERED ([id] ASC)
);

Мои занятия:

public class Dorm
    {
        [Key]
        public int id { get; set; }
        public Dorm() {}
        [DisplayFormat(NullDisplayText = "No address")]
        public Address address { get; set; }
        public string dormName { get; set; }

        public string dormUrl { get; set; }
    }
public class Address
    {
        [Key]
        public int id { get; set; }
        public string street { get; set; }
        public int streetNumber { get; set; }
        public int zipCode { get; set; }

        public string longitude { get; set; }
        public string latitude { get; set; }
}

Пожалуйста, дайте мне знать, если какой-то другой код необходим для решения проблемы

1 Ответ

1 голос
/ 09 июля 2019

JOIN-запросы не выдаются автоматически.Вы должны сделать это, сказав EF загружать отношения охотно или явно.Вы также можете включить отложенную загрузку, но это действительно не рекомендуется.

Быстрая загрузка

var dorms = await _context.Dorms.Include(x => x.Address).ToListAsync();

Явная загрузка

var dorms = await _context.Dorms.ToListAsync();
foreach (var dorm in dorms)
{
    await _context.Entry(dorm).Reference(x => x.Address).LoadAsync();
}

Очевидно, что более ранняя загрузка намного эффективнее, поскольку она выдаст истинное соединение в базе данных.Явная загрузка приведет к отдельным запросам для каждого элемента в списке, но может быть полезна в ситуациях, когда вы хотите загрузить или нет отношения по условию.

Последний вариант - отложенная загрузка.Это требует двух вещей:

  1. Свойство должно быть virtual, то есть public virtual Address Address { get; set; }
  2. Вы должны включить отложенную загрузку через UseLazyLoadingProxies() при настройкеконтекст в ConfigureServices.

    services.AddDbContext<OptimalHousingContext>(o =>
        o.UseLazyLoadingProxies()
         .UseSqlServer(Configuration.GetConnectionString("OptimalHousing")));
    

При отложенной загрузке связь будет загружена точно в срок при обращении к свойству.Вот почему ключевое слово virtual требуется для свойства.EF создаст динамический прокси-класс, который переопределяет ваши ссылки и свойства коллекции, чтобы добавить пользовательский метод получения, который пытается извлечь из кэша объектов, и в случае неудачи выдаст запрос, чтобы получить соответствующий элемент (ы).

Однако, это очень неэффективно, особенно при работе со списками вещей.Он выдаст отдельный запрос для каждого отношения для каждого элемента в списке, что часто приводит к N + 1 запросам или иногда даже N (N + 1) запросам.Чем больше связей и чем глубже ваш объектный граф, тем хуже он становится.Лучше всего всегда просто загружать все, с чем вы хотите работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...