Внешние ключи EF Core не работают с существующей базой данных - PullRequest
0 голосов
/ 01 сентября 2018

Я создаю приложение NET Core MVC, которое использует существующую базу данных MS SQL. Первичные ключи и внешние ключи уже установлены и работают правильно на уровне базы данных.

Я последовал примеру этой статьи и использовал консоль диспетчера пакетов для обратного инжиниринга моделей и контекста базы данных из базы данных. Это, казалось, работало хорошо. В результате все модели были добавлены в папку Models моего приложения, включая надежный класс контекста базы данных. У меня проблема в том, что реляционная информация об этих объектах не заполняется во время выполнения. Я получаю значения NULL для связанных объектов, для которых внешние ключи установлены как в базе данных, так и в свободном API-коде, созданном процессом скаффолдинга.

У меня есть две таблицы, Mode и Submode, связанные через внешний ключ.

Леса сгенерировали эти два класса для двух вышеупомянутых таблиц:

public partial class Submode
{
    public Submode()
    {
        Contact = new HashSet<Contact>();
    }

    public int Id { get; set; }
    public int ModeId { get; set; }
    public string Code { get; set; }
    public bool Visible { get; set; }
    public bool IsDefault { get; set; }

    public Mode Mode { get; set; }
    public ICollection<Contact> Contact { get; set; }
}

public partial class Mode
{
    public Mode()
    {
        Contact = new HashSet<Contact>();
        Submode = new HashSet<Submode>();
    }

    public int Id { get; set; }
    public string Code { get; set; }
    public bool Visible { get; set; }
    public bool IsDefault { get; set; }

    public ICollection<Contact> Contact { get; set; }
    public ICollection<Submode> Submode { get; set; }
}

Scaffolding также сгенерировал этот свободный фрагмент API в контексте базы данных:

            modelBuilder.Entity<Submode>(entity =>
        {
            entity.HasIndex(e => e.Code)
                .HasName("UQ__Submode__A25C5AA75D2A9AE7")
                .IsUnique();

            entity.Property(e => e.Code)
                .IsRequired()
                .HasMaxLength(100)
                .IsUnicode(false);

            entity.HasOne(d => d.Mode)
                .WithMany(p => p.Submode)
                .HasForeignKey(d => d.ModeId)
                .OnDelete(DeleteBehavior.ClientSetNull)
                .HasConstraintName("FK_Submode_ModeId");
        });

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

Ноль во время выполнения

И я получаю исключение нулевой ссылки в возвращенном представлении, потому что я пытаюсь отобразить свойства связанного объекта Mode. Я пропустил какую-то конфигурацию или есть проблема со скаффолдинговым кодом?

UDPATE - по запросу, вот реализация, которая извлекает данные из контекста базы данных.

public class SQLSubModeData : ISubModeData
{
    private w4lkrContext _context;

    public SQLSubModeData(w4lkrContext context)
    {
        _context = context;
    }

    public IQueryable<Submode> Get()
    {
        return _context.Submode.OrderBy(p => p.Id);
    }

    public Submode Get(int id)
    {
        return _context.Submode.FirstOrDefault(p => p.Id == id);
    }
}

ОБНОВЛЕНИЕ (решено) - Включение отложенной загрузки решило проблему. Три шага привели меня туда:

  1. Установленные Microsoft.EntityFrameworkCore.Proxies (2.1.2) через NuGet

  2. Обновлен метод Startup.cs -> AddDbContext (), как показано ниже:

    services.AddDbContext (options => options.UseLazyLoadingProxies (). UseSqlServer (_configuration.GetConnectionString ("W4LKR")));

  3. Сделаны все свойства навигации виртуальными. Это должно было быть сделано для каждой модели в приложении, а не только для той, которая вызывается в моем примере выше. Ошибки выдаются, если хотя бы один из них пропущен.

1 Ответ

0 голосов
/ 01 сентября 2018

Но режим возвращается к нулю для подрежима.

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

См. Загрузка связанных данных

...