无法翻译 EF 核心查询

时间:2021-02-26 13:13:56

标签: c# entity-framework wildcard sql-like

我正在尝试开发一些需要运行以下复杂查询的动态类型的代码。

tag_user

实际上我想找到包含其中一个 searchKeys 的行。例如,如果我有这样的搜索键:

public function up()
    {
        Schema::create('tags', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('label');
            $table->timestamps();
        });

        Schema::create('tag_user', function (Blueprint $table) {
            $table->unsignedBigInteger('tag_id');
            $table->foreign('tag_id')->references('id')->on('tags')->onDelete('cascade');
            $table->unsignedBigInteger('user_id');
            $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
            $table->primary(['tag_id','user_id']);
        });
    }

然后我想找到例如名称为 IEnumerable<string> searchKeys = search.KeySearch.Split(',').Select(key => key.Trim()); var searchedIds = _dbContext.Keys .Where(key => searchKeys.Any(searchKey => EF.Functions.Like(key.Name, searchKey))) 或名称为 var searchKeys = ["name_%", "last_x%]; 的行。
但是 ef cores 说它无法翻译,并建议要么编写可翻译的查询,要么在客户端执行查询(这在我的问题中不合适)。

<块引用>

System.InvalidOperationException: LINQ 表达式 'DbSet() .Where(k => __searchKeys_0 .Any(searchKey => __Functions_1 。像( 匹配表达式:k.Name, 模式:searchKey)))' 无法翻译。要么以可翻译的形式重写查询,要么切换到客户端 通过插入对“AsEnumerable”、“AsAsyncEnumerable”、“ToList”或“ToListAsync”的调用来显式评估。有关详细信息,请参阅 https://go.microsoft.com/fwlink/?linkid=2101038

所以我想将查询更改为可翻译的查询,但我不知道是什么问题,也没有开始修复它的线索。

1 个答案:

答案 0 :(得分:2)

因此以下解决方案至少应该有效:

var searchKeys = search.KeySearch.Split(',').Select(key => key.Trim());

var queries = new List<IQueryable<Key>>();
foreach (var searchKey in searchKeys)
{
    queries.Add(_dbContext.Keys.Where(k => EF.Functions.Like(k.Name, searchKey)));
}

var finalQuery = queries[0];
for (var i = 1; i < queries.Count; i++)
{
    finalQuery = finalQuery.Union(queries[i]);
}

var filteredKeys = finalQuery.ToList();

我认为代码效率很低,因为它会导致多个 UNION 语句。

一个更高效的选择是构建一个表达式树 Expression<Func<Key, bool>>,它基本上产生以下结果:.Where(k => EF.Functions.Like(k.Name, searchKey[0]) || ... || EF.Functions.Like(k.Name, searchKey[5]))