即使数据输入似乎正确,也无法在核心2.2中输出外键对象

时间:2019-07-09 10:06:49

标签: sql asp.net-core .net-core foreign-keys

我有一个具有地址字段(地址类型)的复杂类型(宿舍),但是当我在宿舍上调试函数时,它具有地址字段= 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 个答案:

答案 0 :(得分:1)

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

显然,耳环加载程序效率更高,因为它将在数据库中发出真正的JOIN。显式加载将导致对列表中的每个项目进行单独的查询,但是在您希望有条件地加载或不关联的情况下很有用。

最后一个选项是延迟加载。它需要两件事:

  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)个查询。关系越多,对象图越深,它就会变得越差。最好的选择是始终热切加载您想要使用的任何内容。