Sql 无法在core 2.2中输出外键对象,即使数据项似乎正确
我有一个复杂类型(Dorm),它有一个地址字段(address type),但是当我在Dorms上调试一个函数时,它的地址字段为null,即使当我打开数据库资源管理器时,addressID外键被正确填充 我已经确定SQL是正确的,但现在不确定在哪里查找错误 dbcontext如下所示,我认为这可能就是问题所在Sql 无法在core 2.2中输出外键对象,即使数据项似乎正确,sql,asp.net-core,.net-core,foreign-keys,Sql,Asp.net Core,.net Core,Foreign Keys,我有一个复杂类型(Dorm),它有一个地址字段(address type),但是当我在Dorms上调试一个函数时,它的地址字段为null,即使当我打开数据库资源管理器时,addressID外键被正确填充 我已经确定SQL是正确的,但现在不确定在哪里查找错误 dbcontext如下所示,我认为这可能就是问题所在 namespace OptimalHousing.Models { public class OptimalHousingContext : 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].[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; }
}
请告诉我是否需要其他代码来解决此问题连接查询不会自动发出。您必须通过告诉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();
}
显式加载
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();
}
显然,earger加载效率更高,因为它将在数据库中发出真正的连接。显式加载将导致对列表中的每个项目进行单独的查询,但在您希望有条件加载或不加载关系的情况下,这可能非常有用
最后一个选项是延迟加载。它需要两件事:
virtual
,即公共虚拟地址{get;set;}
ConfigureServices
中配置上下文时,必须通过UseLazyLoadingProxies()
启用延迟加载
services.AddDbContext<OptimalHousingContext>(o =>
o.UseLazyLoadingProxies()
.UseSqlServer(Configuration.GetConnectionString("OptimalHousing")));
services.AddDbContext(o=>
o、 使用LazyLoadingProxies()
.UseSqlServer(Configuration.GetConnectionString(“OptimalHousing”));
virtual
关键字的原因。EF将创建一个动态代理类,该类重写引用和集合属性,以添加一个试图从对象缓存中提取的自定义getter,如果失败,则发出查询以获取相关项
然而,这是非常低效的,尤其是在处理一系列事情时。它将为列表中的每个项目的每个关系发出单独的查询,通常会导致N+1查询,有时甚至是N(N+1)查询。关系越多,对象图越深,情况就越糟。你最好的选择是总是急切地加载你想使用的任何东西。它适用于我的函数,如问题中所问:),但是我可以这样做吗:
@Html.DisplayFor(modeleItem=>item.address)
在我的htmlSure中?我的意思是,如果您在address
中实际获得了一些数据,但DisplayFor
是一个模板化的帮助器,并且我认为它无法处理在没有该类型的实际模板的情况下渲染整个对象的功能EditorFor
can,但是,它基本上只是为类型上的所有属性添加一个输入和标签,这是一个基本的默认值。没有多个值的默认显示。