LinqToDB关系返回null

时间:2020-09-06 02:13:16

标签: c# asp.net linq asp.net-core

我一直在尝试获取一个名为AppUser及其详细信息的实体。我使用了两种不同的方法来获取用户及其关系。

我使用了 linq联接查询包含扩展方法,但是被称为UserDetail的关系对于它们两个都返回null。 >

enter image description here

这是我的实现方式。

    public AppUserDetailDto GetUserDetailByUserName(string userName)
    {
        //TODO: Code needs to be refactored
        if (string.IsNullOrEmpty(userName))
            throw new ArgumentNullException(nameof(userName));

        var appuser = from user in _appUserRepository.Table
                      join userdetail in _appUserDetailRepository.Table on user.DetailId equals 
                      userdetail.Id
                      where user.userName == userName
                      select user;

        var deger = _appUserRepository.Find(x => x.UserName == userName, x => x.Include(t => t.UserDetail)).FirstOrDefault();

        var user2 = _userManager.Users.FirstOrDefault(x => x.UserName == userName);
        _userManager.Users.Include(u => u.UserDetail);

        var detail = user2.UserDetail;

        return null;
    }

这是我的AppUser类。

    public class AppUser : BaseEntity, IAppUser
{
    [Required, Identity]
    [Key]
    public new int Id { get; set; }

    [Required]
    [ForeignKey("UserDetail")]
    public int DetailId { get; set; }

    public virtual AppUserDetail UserDetail { get; set; }
    public string UserName { get; set; }
    public string NormalizedUserName { get; set; }
    public string PasswordHash { get; set; }
    public bool EmailConfirmed { get; set; }
    public string Email { get; set; }
    public string NormalizedEmail { get; set; }
    public DateTimeOffset? LockoutEnd { get; set; }
    public int AccessFailedCount { get; set; }
    public bool LockoutEnabled { get; set; }
    public string PhoneNumber { get; set; }
    public bool PhoneNumberConfirmed { get; set; }
    public string SecurityStamp { get; set; }
    public bool TwoFactorEnabled { get; set; }
    public string ConcurrencyStamp { get; set; }
}

查询在Sql Server端正常运行。

enter image description here

我该如何解决?

3 个答案:

答案 0 :(得分:0)

我对LINQ查询不是很好,所以我将讨论您尝试的另一种方法。

尝试一下-

var user2 = _userManager.Users.Include(u => u.UserDetail).FirstOrDefault(x => x.UserName == userName);
var detail = user2.UserDetail;

使用当前代码,使用以下代码行提取用户-

var user2 = _userManager.Users.FirstOrDefault(x => x.UserName == userName);

添加此行-

_userManager.Users.Include(u => u.UserDetail);

什么也不会做。它不会执行任何操作,因此不会从数据库中获取相关的UserDetail实体。它只是其中包含LINQ表达式的C#语句。要使其执行(将其转换为SQL查询),必须在其上调用FirstFirstOrDefaultToList等方法。

答案 1 :(得分:0)

您应该在select中指定UserDetail。

    var appuser = from user in _appUserRepository.Table
                  join userdetail in _appUserDetailRepository.Table on user.DetailId equals 
                  userdetail.Id
                  where user.userName == userName
                  select new
                  {
                      user,
                      userdetail
                  };

答案 2 :(得分:0)

已通过使用LinqToDB LoadWith扩展方法并为我的AppUser和AppUserDetail使用关联映射属性解决了此问题。包含扩展方法不能用于LinqToDB实现。

这是我的AppUser类。

public class AppUser : BaseEntity, IAppUser
{
    [Required, Identity]
    [Key]
    public new int Id { get; set; }

    [Required]
    [ForeignKey("UserDetail")]
    public int DetailId { get; set; }

    [LinqToDBAssociation.Association(ThisKey = nameof(DetailId), OtherKey = nameof(AppUserDetail.Id), CanBeNull = true, Relationship = Relationship.OneToOne)]
    public virtual AppUserDetail UserDetail { get; set; }

    public string UserName { get; set; }
    public string NormalizedUserName { get; set; }
    public string PasswordHash { get; set; }
    public bool EmailConfirmed { get; set; }
    public string Email { get; set; }
    public string NormalizedEmail { get; set; }
    public DateTimeOffset? LockoutEnd { get; set; }
    public int AccessFailedCount { get; set; }
    public bool LockoutEnabled { get; set; }
    public string PhoneNumber { get; set; }
    public bool PhoneNumberConfirmed { get; set; }
    public string SecurityStamp { get; set; }
    public bool TwoFactorEnabled { get; set; }
    public string ConcurrencyStamp { get; set; }

    [LinqToDBAssociation.Association(ThisKey = "Id", OtherKey = "CreatedBy", CanBeNull = true)]
    public virtual IEnumerable<Post> UserPosts { get; set; }
}

这是我的代码实现。

    /// <summary>
    /// Returns an user detail by username
    /// </summary>
    /// <param name="userName"></param>
    /// <returns></returns>
    public AppUserDetailDto GetUserDetailByUserName(string userName)
    {
        //TODO: Code needs to be refactored
        if (string.IsNullOrEmpty(userName))
            throw new ArgumentNullException(nameof(userName));

        var appUser = _appUserRepository.Table.LoadWith(t => t.UserDetail).FirstOrDefault(x => x.UserName == userName);

        AppUserDetailDto dto = new AppUserDetailDto
        {
            Id = appUser.Id,
            UserName = appUser.UserName,
            CoverPhotoUrl = appUser.UserDetail.CoverPhotoPath,
            ProfilePhotoUrl = appUser.UserDetail.ProfilePhotoPath,
            RegisteredDate = appUser.CreatedDate,
            UserPosts = _postService.GetUserPostsWithDto(appUser.Id)
        };

        return dto;
    }