Linq通过搜索关键字从对象的关系列表中选择对象

Posted

技术标签:

【中文标题】Linq通过搜索关键字从对象的关系列表中选择对象【英文标题】:Linq selecting object from relational list of object by search keyword 【发布时间】:2020-08-14 18:18:17 【问题描述】:

我想使用搜索关键字获取学校校长。学校 可以有一个用户列表,其中一个是主要角色。

现在我的问题是我正在实现一个自动搜索,它需要 关键字并根据学校名称、代码和校长进行搜索 名字。

代码:

 public class School : AuditableDataEntity<int>
    
        [Required]
        [MaxLength(200)]
        public string Name  get; set; 

        [MaxLength(150)]
        public string Code  get; set; 

        public District District  get; set; 

        public ICollection<UserProfile> Users  get; set; 


    

public class UserProfile : AuditableDataEntity<Guid>
    

        [Required]
        [MaxLength(100)]
        public string FirstName  get; set; 

        [Required]
        [MaxLength(100)]
        public string LastName  get; set; 

        [Required]
        [MaxLength(200)]
        public string Email  get; set; 

        [MaxLength(50)]
        public string PhoneWork  get; set; 

        [MaxLength(20)]
        public int PhoneWorkExt  get; set; 

        [MaxLength(50)]
        public string PhoneMobile  get; set;        

        public UserLevel UserLevel  get; set; 

        public UserRole UserRole  get; set; 

        public UserDesignation UserDesignation  get; set; 

        public School School  get; set; 
        public int? SchoolId  get; set; 

        public string FullName => $"FirstName LastName";
    

Task<Response<IEnumerable<SchooSearchDTO>>> ISchoolQueryService.GetSchoolAutoCompleteData(string searchKeyword)
        
            return _schoolQueryRepository.WithRelatedEntities().Where(x => x.Name.Contains(searchKeyword)
            ||x.Code.Contains(searchKeyword)
            || x.Users.FirstOrDefault(y => y.DataEntityState == DataEntityState.Published && y.UserDesignation == UserDesignation.Principal).FullName.Contains(searchKeyword)).OrderBy(u => u.Name).Select(z => new SchooSearchDTO
            
                PrincipalName = z.Name,
                CDSCode = z.Code

            ).ToResponseListAsync();
        

错误:

LINQ 表达式 'DbSet .Where(s => s.Name.Contains(__searchKeyword_0) || s.CDSCode.Contains(__searchKeyword_0) || DbSet .Where(u => EF.Property>(s, "Id") != null && EF.Property>(s, "Id") == EF.Property>(u, “学校标识”)) .Where(u => (int)u.DataEntityState == 1 && (int)u.UserDesignation == 1) .Select(u => u.FullName) .FirstOrDefault().Contains(__searchKeyword_0))' 无法翻译。要么以可以翻译的形式重写查询, 或通过插入调用显式切换到客户端评估 AsEnumerable()、AsAsyncEnumerable()、ToList() 或 ToListAsync()。见https://go.microsoft.com/fwlink/?linkid=2101038 更多信息。

【问题讨论】:

【参考方案1】:

问题在于 EF 无法将其转换为 SQL。

x.Users.FirstOrDefault(y => y.DataEntityState == DataEntityState.Published && y.UserDesignation == UserDesignation.Principal).FullName.Contains(searchKeyword)

所以尝试使用Any 而不是在LINQ 中选择带有FirstOrDefault 的用户,以便EF 能够将其翻译成SQL。

Task<Response<IEnumerable<SchooSearchDTO>>> ISchoolQueryService.GetSchoolAutoCompleteData(string searchKeyword)

    return _schoolQueryRepository.WithRelatedEntities().Where(x => x.Name.Contains(searchKeyword)
        ||x.Code.Contains(searchKeyword)
        || x.Users.Any(y => y.DataEntityState == DataEntityState.Published && y.UserDesignation == UserDesignation.Principal && y.FirstName.Contains(searchKeyword))
    ).OrderBy(u => u.Name).Select(z => new SchooSearchDTO
    
        PrincipalName = z.Name,
        CDSCode = z.Code

    ).ToResponseListAsync();

见:The LINQ expression could not be translated and will be evaluated locally

编辑:

您还需要使用FirstName,因为FullName 是您在SQL 中没有的属性。

【讨论】:

同样的错误,需要寻找其他方法。 它通过更改 && y.FirstName.Contains(searchKeyword) 起作用,问题是与 FullName 相关的,因此它通过更改为 Any 并将 FullName 更改为 FirstName 来起作用。 是的,好点,我忘了提到..我已经更新了我的答案。

以上是关于Linq通过搜索关键字从对象的关系列表中选择对象的主要内容,如果未能解决你的问题,请参考以下文章

使用 LINQ,在另一个对象列表中选择对象列表

如何使用 LINQ 从对象列表中获取唯一的属性列表?

将关键字存储在查询集中,在结果查询集中提供带有 Q 对象的搜索命中以及搜索结果

Linq 从一个列表中获取对象,其中其他整数列表包含在第一个列表中

如何在没有 Linq 的情况下从列表中获取一些对象?

如何选择具有最低属性 linq 查询语法的对象