简体   繁体   English

从ID为外键的表中加载对象

[英]Load object from table with id as foreign key

i have define users with UserRole type Role as foreing key of another table. 我已将UserRole类型为Role的用户定义为另一个表的前键。 Entiti framework auto transformed name UserRole to UserRoleId with type integer (Id). Entiti框架自动将名称UserRole转换为类型为整数(Id)的UserRoleId。 Its ok. 没关系。 But i have UserRoleId = 2 in table User table preview and when i trying get user by Id: 但是我在表用户表预览中有UserRoleId = 2,并且当我尝试通过ID获取用户时:

var user = await _userManager.FindByIdAsync(id);

so parameter UserRole is null user preview from debuging . 因此参数UserRole为调试时的用户预览

Application user: 应用程序用户:

public class ApplicationUser : IdentityUser
{
    public int PriorityLevel { get; set; }
    public Role UserRole { get; set; }
    public string ForName { get; set; }
    public string LastName { get; set; }
    public string Mobile { get; set; }
    public string WorkPlace { get; set; }
    public string Notice { get; set; }
}

Must i use some entity framework command for load UserRole as type Role? 我是否必须使用某些实体框架命令来将UserRole加载为Role类型? Or can i get UserRoleId from table? 或者我可以从表中获取UserRoleId?

Thanks for any advice. 感谢您的任何建议。

You tagged your question with Entity Framework, but just in case, I'll cover Entity Framework Core, as well, since they diverge slightly on this. 您用Entity Framework标记了您的问题,但以防万一,我也将介绍Entity Framework Core,因为它们在此方面略有不同。

Entity Framework supports lazy-loading, but importantly, the property must be virtual to enable that, ie: 实体框架支持延迟加载,但是重要的是,该属性必须是virtual才能启用,即:

public virtual Role UserRole { get; set; }

EF adds the logic necessary to do lazy-load the property by deriving a dynamic "proxy" class from your entity and overriding the property. EF通过从您的实体派生动态“代理”类并覆盖该属性来添加延迟加载属性所需的逻辑。 Since non- virtual properties cannot be overridden, this logic is not added to properties without virtual . 由于非virtual属性不能被覆盖,因此该逻辑不会添加到没有virtual属性的属性中。 Without virtual , navigation properties will not be loaded automatically, and will remain null , whether there's associations in the database or not. 如果没有virtual ,则导航属性将不会自动加载,并且无论数据库中是否存在关联,导航属性将保持null

Entity Framework Core does not support lazy-loading at all , so adding virtual will not help you. 实体框架的核心不支持延迟加载可言 ,所以加入virtual不会帮你。

In either case, you should really be eager-loading, instead. 无论哪种情况,您都应该真正渴望加载。 This is done by adding Include to your query. 这是通过在查询中添加“ Include来完成的。 However, you have two problems there: 但是,那里有两个问题:

  1. UserManager<TUser> doesn't support including related entities. UserManager<TUser>不支持包括相关实体。 You would need to use the DbSet , ie context.Users . 您将需要使用DbSet ,即context.Users

  2. You cannot use Include with Find (or any of the Find -related methods), as it has logic that is incompatible with doing joins. 您不能将IncludeFind (或任何与Find相关的方法)一起使用,因为它的逻辑与进行联接不兼容。 Namely, Find attempts to pull the entity from the context cache without doing a query at all, if possible, and as such, cannot guarantee that navigation properties can be included. 即,如果可能的话, Find尝试从上下文缓存中拉出实体而不进行任何查询,因此,这种尝试无法保证可以包含导航属性。 As a result, you will have to switch to something like SingleOrDefault . 结果,您将不得不切换到SingleOrDefault类的SingleOrDefault

var user = await context.Users.Include(x => x.UserRole).SingleOrDefault(x => x.Id == id);

With that, UserRole should now actually have a value. 这样, UserRole现在实际上应该具有一个值。

Alternatively, you should be able to explicitly-load UserRole : 另外,您应该能够显式加载UserRole

var user = await _userManager.FindByIdAsync(id);
context.Entry(user).Reference(s => s.UserRole).Load();

This methodology is the same in both Entity Framework and Entity Framework Core. 在实体框架和实体框架核心中,此方法都是相同的。 However it was only introduced into EF Core in 1.1, so be cognizant of the version you're running. 但是,它仅是在1.1中引入到EF Core中的,因此请注意所运行的版本。 The one downside here is that this will result in (potentially) two queries. 这里的缺点是这将导致(潜在地)两个查询。 Again, since the Find methods attempt to retrieve from the context cache, it's possible you'll avoid a query there, but the entity is not in the cache, it will take two queries: one for the user and one for the related role. 同样,由于Find方法尝试从上下文缓存中检索,因此有可能避免在该查询中进行查询,但是该实体不在缓存中,因此它将执行两个查询:一个查询给用户,一个查询给相关角色。 However, that would have been the case as well with lazy-loading. 但是,延迟加载也是如此。 Only eagerly-loading allows the queries to be combined using JOIN s. 只有急切的加载才允许使用JOIN组合查询。

您可以使用此方法获得用户的所有角色。

_userManager.GetRolesAsync(id);

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

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