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

时间:2018-09-01 15:14:09

标签: database entity-framework loading lazy-evaluation core

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

我遵循了this article中的示例,并使用程序包管理器控制台对数据库中的模型和数据库上下文进行了反向工程。这似乎运作良好。结果导致所有模型都添加到我的应用程序的Models文件夹中,其中包括健壮的数据库上下文类。我遇到的问题是,在运行时没有填充有关这些实体的关系信息。对于在数据库和由脚手架过程生成的流利的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; }
}

脚手架还在数据库上下文中生成了此流利的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设置外键的示例都显示出与上述代码段相似的模式。但是对于子模式,“模式”返回空值。

Null at runtime

我在返回的视图中得到一个空引用异常,因为我试图显示相关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. 通过NuGet安装了Microsoft.EntityFrameworkCore.Proxies(2.1.2)

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

    services.AddDbContext(options => options.UseLazyLoadingProxies()。UseSqlServer(_configuration.GetConnectionString(“ W4LKR”)));

  3. 将所有导航属性设为虚拟。必须在应用程序中的每个模型上完成此操作,而不仅仅是在我上面的示例中调用的模型。即使连一个错误都抛出错误。

1 个答案:

答案 0 :(得分:1)

  

但是对于子模式,模式返回空值。

由于未将导航属性声明为virtual,因此您已禁用了延迟加载,因此EF仅在进行紧急加载或显式加载时才会填充导航属性。

请参见Loading Related Data