使用用户管理器预先加载

本文关键字:加载 管理器 用户 | 更新日期: 2023-09-27 17:56:02

所以我创建了这个继承自UserManager的用户服务,它看起来像这样:

/// <summary>
/// Service for handling users
/// </summary>
public class UserService : UserManager<User>
{
    /// <summary>
    /// Default constructor
    /// </summary>
    /// <param name="store">The user repository</param>
    public UserService(IUserStore<User> store)
        : base(store)
    {
        // Allow the user service to use email instead of usernames
        this.UserValidator = new UserValidator<User>(this)
        {
            AllowOnlyAlphanumericUserNames = false
        };
    }
    /// <summary>
    /// A static method that creates a new instance of the user service
    /// </summary>
    /// <param name="options">Any options that should be supplied</param>
    /// <param name="context">The Owin context</param>
    /// <returns>The user service</returns>
    public static UserService Create(IdentityFactoryOptions<UserService> options, IOwinContext context)
    {
        // Get our current database context
        var dbContext = context.Get<DatabaseContext>();
        // Create our service
        var service = new UserService(new UserStore<User>(dbContext));
        // Allow the user service to use email instead of usernames
        service.UserValidator = new UserValidator<User>(service)
        {
            AllowOnlyAlphanumericUserNames = false
        };
        // Assign our email service to our user service
        service.EmailService = new EmailService();
        // Get our data protection provider
        var dataProtectionProvider = options.DataProtectionProvider;
        // If our data protection provider is not nothing
        if (dataProtectionProvider != null)
        {
            // Set our token provider
            service.UserTokenProvider = new DataProtectorTokenProvider<User>(dataProtectionProvider.Create("ASP.NET Identity"))
            {
                // Code for email confirmation and reset password life time
                TokenLifespan = TimeSpan.FromHours(6)
            };
        }
        // Return our service
        return service;
    }
}

但是我已经在我的 DbContext 中禁用了 LazyLoad。所以,现在我有一个问题。用户可以拥有中心,但它们主要属于公司,因此创建了一个查找表,我已经在我的 DbContext 中映射了该表,如下所示:

// Create lookup tables
modelBuilder.Entity<Center>()
    .HasMany(m => m.Users)
    .WithMany(m => m.Centers)
    .Map(m =>
    {
        m.MapLeftKey("CenterId");
        m.MapRightKey("UserId");
        m.ToTable("UserCenters");
    });

所以,现在我需要访问用户的中心,但身份框架似乎不支持预先加载。以前有没有人发现这是一个问题,有谁知道我如何将 EagerLoading 与用户管理器一起使用?

干杯/r3plica

使用用户管理器预先加载

该死的,这很容易解决。UserManager实际上将用户DbSet公开为IQueryable,因此您可以在此处添加"包含",因此我刚刚创建了此功能:

/// <summary>
/// Gets all users
/// </summary>
/// <param name="includes">Optional parameter for eager loading related entities</param>
/// <returns>An list of users</returns>
public IQueryable<User> GetAll(params string[] includes) {
    // Get our User DbSet
    var users = base.Users;
    // For each include, include in the query
    foreach (var include in includes)
        users = users.Include(include);
    // Return our result
    return users;
}

然后在我的控制器中,我这样做了:

/// <summary>
/// Gets the centers assigned to a user
/// </summary>
/// <param name="userId">The id of the user</param>
/// <returns>All centers for the user</returns>
[HttpGet]
[Route("", Name = "GetCentersByUser")]
public IHttpActionResult Get(string userId)
{
    // Get our user
    var user = this.UserService.GetAll("Centers").Where(m => m.Id.Equals(userId, StringComparison.OrdinalIgnoreCase)).SingleOrDefault();
    // If the user doesn't exist, throw an error
    if (user == null)
        return BadRequest("Could not find the user.");
    // Return our centers
    return Ok(user.Centers.Select(m => this.ModelFactory.Create(m)));
}