EF Core 外键不适用于现有数据库

EF Core foreign keys not working with existing database

我正在构建一个使用现有 MS SQL 数据库的 NET Core MVC 应用程序。主键和外键已经建立并在数据库级别正常工作。

我按照 this article 中的示例并使用程序包管理器控制台对数据库中的模型和数据库上下文进行逆向工程。这似乎运作良好。它导致所有模型都被添加到我的应用程序的模型文件夹中,包括强大的数据库上下文 class。我遇到的问题是关于这些实体的相关信息没有在运行时填充。我在数据库和脚手架过程生成的流畅 API 代码中为其建立外键的相关实体得到空值。

我有两个表,Mode 和 Submode,它们通过外键关联。

脚手架为以上两个表生成了这两个 classes:

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; }
}

脚手架还在数据库上下文中生成了这个流畅的 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 返回 null。

Null at runtime

并且我在返回的视图中得到一个空引用异常,因为我试图显示相关模式对象的属性。我是否缺少某些配置或脚手架代码是否存在问题?

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. 已通过 NuGetMicrosoft.EntityFrameworkCore.Proxies(2.1.2) 安装

  2. 更新了Startup.cs -> AddDbContext()方法,如下:

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

  3. 使所有导航属性虚拟化。这必须在应用程序中的每个模型上完成,而不仅仅是在我上面的示例中调用的模型。漏掉一个也会报错。

But Mode comes back null for Submode.

由于您的导航属性未声明为 virtual,您已禁用延迟加载,因此 EF 将仅在您执行预先加载或显式加载时填充您的导航属性。

Loading Related Data