EF Core 过滤器枚举使用 LIKE 运算符存储为字符串

EF Core filter Enums stored as string with LIKE operator

我有一个带有 Gender 枚举属性的 Person 模型,它作为字符串存储在数据库中。 我想查询以按性别的子字符串过滤数据。例如,如果 query.SearchLike"Fe""em",我想找回每个女性。 不幸的是,下面的代码抛出异常。

builder.Entity<Person>().Property(x => x.Gender).HasConversion<string>();
public async Task<IList<Person>> ListAsync(PersonsQuery query)
{
  IQueryable<Person> queryable = _context.Persons.AsNoTracking();

  return await queryable
    .Where(x => x.Gender.ToString().Contains(query.SearchLike))
    .ToListAsync();
}

异常:

The LINQ expression 'DbSet\r\n .Where(x => x.Gender.ToString().Contains(__query_SearchLike_0))' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync(). See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.

据我了解,您应该使用 EF Like 函数。尝试这样的事情:

public async Task<IList<Person>> ListAsync(PersonsQuery query)
{
  IQueryable<Person> queryable = _context.Persons.AsNoTracking();

  return await queryable
    .Where(x => EF.Functions.Like(x.Gender, "%" + query.SearchLike + "%")
    .ToListAsync();
}

我找到了解决方案。 首先需要将枚举转换为 object 然后转换为 string.

public async Task<IList<Person>> ListAsync(PersonsQuery query)
{
  IQueryable<Person> queryable = _context.Persons.AsNoTracking();

  return await queryable
    .Where(x => ((string)(object)x.Gender).Contains(query.SearchLike))
    .ToListAsync();
}

EF Core Github repo中的相关问题。

您可以使用 FromSql 方法执行原始 SQL 语句

public async Task<IList<Person>> ListAsync(PersonsQuery query)
{    
    var param = $"%{query.SearchLike}%"
    return await _context.Persons
        .FromSql("SELECT * FROM Persons WHERE Gender LIKE {0}" , param)
        .ToListAsync();
}