简体   繁体   English

急切加载的实体框架问题

[英]Entity Framework problem with eager loading

在此处输入图像描述 在此处输入图像描述

I want to create a new TrackingItem , but response from the server is:我想创建一个新的TrackingItem ,但服务器的响应是:

在此处输入图像描述

I don't know how to include the Tenant property.我不知道如何包含Tenant属性。

When working with navigation properties, populate the navigation properties, not just the FKs.使用导航属性时,填充导航属性,而不仅仅是 FK。

The issue you are likely seeing is that when you call code to add a Tracking Item, the DbContext will start tracking that instance, however you have only set the TenantId on that instance, not the Tenant Navigation property.您可能会看到的问题是,当您调用代码添加跟踪项时,DbContext 将开始跟踪该实例,但是您只在该实例上设置了 TenantId,而不是 Tenant Navigation 属性。 Any code that gets that TrackingItem reference from the DbContext and tries to go to.Tenant.* will get that exception because while a TenantID was provided, no Tenant was loaded.任何从 DbContext 获取该 TrackingItem 引用并尝试将 go to.Tenant.* 的代码都会得到该异常,因为虽然提供了 TenantID,但没有加载任何租户。 For a new instance I don't believe lazy loading would even kick in, and you don't appear to be enabling lazy loading to begin with.对于一个新实例,我认为延迟加载甚至不会启动,而且您似乎并没有从一开始就启用延迟加载。 (Tenant is not declared as virtual ) (租户未声明为virtual

Now doing this with generic repositories is a pain since you've wrapped the DbContext in a Repository that's specific to Tracking Items, so that will need some sorting out.现在使用通用存储库执行此操作很痛苦,因为您已将 DbContext 包装在特定于跟踪项目的存储库中,因此需要进行一些整理。 With a DbContext reference it would need to look something like:使用 DbContext 引用,它需要看起来像:

var tenant = _context.Tenants.Single(x => x.TenantId == tenantId);
var trackingItem = new TrackingItem
{
    Tenant = tenant,
    // .. remaining TrackingItem fields...
}
_context.TrackingItems.Add(trackingItems);
await _context.SaveChangesAsync();

When using navigation properties, I recommend not declaring FK properties, but instead using shadow properties for the FK.使用导航属性时,我建议不要声明 FK 属性,而是使用 FK 的阴影属性。 The issue with declaring FKs alongside navigation properties is that you have 2 sources of truth for the relationship (.TenantId and.Tenant.TenantId) which can be changed independently of one another.与导航属性一起声明 FK 的问题是您有 2 个关系的真实来源(.TenantId 和.Tenant.TenantId),它们可以相互独立地更改。 The behaviour when editing the FK can also vary depending on whether the navigation property is loaded or not.编辑 FK 时的行为也可能因是否加载导航属性而异。

It also means whenever you fetch a TrackingInstance, if the code is going to want to check the Tenant either lazy loading needs to be initialized or you need to remember to eager load Tenant when loading the tracking instance:这也意味着每当您获取 TrackingInstance 时,如果代码要检查 Tenant,要么需要初始化延迟加载,要么您需要记住在加载跟踪实例时预先加载 Tenant:

var trackingItem = _context.TrackingItems
    .Include(x => x.Tenant)
    .Single(x => x.TrackingItemId == trackingItemId);

Enabling lazy loading would help avoid the exception if you forget to eager load the Tenant, though it has its limitations (the DbContext still needs to be in-scope) and it can result in a significant performance cost if you rely on it too much.如果您忘记预先加载租户,启用延迟加载将有助于避免异常,尽管它有其局限性(DbContext 仍然需要在范围内)并且如果您过度依赖它可能会导致显着的性能成本。 (ie get lazy) (即变得懒惰)

Instead, I highly recommend using Projection /w Select or ProjectTo (Automapper) to populate view models when reading data where you might want details from related entities.相反,我强烈建议在读取数据时使用 Projection /w SelectProjectTo (Automapper) 填充视图模型,您可能需要相关实体的详细信息。 This produces more optimized queries and you don't need to worry about eager loading or tripping up on lazy loading when dealing with related entities.这会产生更优化的查询,并且您无需担心在处理相关实体时急切加载或延迟加载。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM