如何使用具体类型(又名 "The LINQ expression could not be translated" 问题)与 EF Core 5 建立条件?

How to make a condition with EF Core 5 using concrete type (aka "The LINQ expression could not be translated" issue)?

我正在尝试进行连接然后过滤结果:

var result = context.Test1
    .Join(context.Test2, q => q.Test11, q => q.Test21, (q, p) => new Tuple<Test1, Test2>(q, p))
    .Where(q => q.Item1.Test2 == "test")
    .ToList();

以上查询抛出异常:

The LINQ expression 'DbSet<Test1>()
.Join(
    inner: DbSet<Test2>(), 
    outerKeySelector: t => t.Test11, 
    innerKeySelector: t0 => t0.Test21, 
    resultSelector: (t, t0) => new TransparentIdentifier<Test1, Test2>(
        Outer = t, 
        Inner = t0
    ))
.Where(ti => new Tuple<Test1, Test2>(
    ti.Outer, 
    ti.Inner
).Item1.Test2 == "test")' could not be translated

问题在这里:new Tuple<Test1, Test2>(ti.Outer, ti.Inner).Item1.Test2 == "test")。当我使用匿名类型进行连接时,效果很好:

var result = context.Test1
    .Join(context.Test2, q => q.Test11, q => q.Test21, (q, p) => new { q, p })
    .Where(q => q.q.Test2 == "test")
    .ToList();

但问题是我正在动态构建查询(使用 PredicateBuilder),因此我需要一个具体类型才能构建查询。所以我使用的方法如下:

private static Expression<Func<Tuple<Test1, Test2>, bool>> GetTransactionsSearchPredicate(string[] values)
{
    var searchPredicate = PredicateBuilder.False<Tuple<Test1, Test2>>();

    foreach (var val in values)
    {
        searchPredicate = searchPredicate.Or(q => q.Item1.Test2 == val);
    }

    return searchPredicate;
}

我也尝试将 Tuple 更改为自定义类型,但错误是一样的。

我可以做些什么来完成这项工作吗?它曾经与 EF Core 2 一起使用,但我认为它只是在本地执行......

System.Tuple EF Core 版本之间的支持不断 changing/breaking,因此其使用不可靠。

对于 EFC 5.0.10(此时最新官方),它不起作用,但是自定义泛型类型 with settable properties(而不是不可变类型 with constructor as System.Tuple) 确实如此。例如如果您将 Tuple 替换为具有以下签名的 Pair

public class Pair<T1, T2>
{
    public T1 Item1 { get; set; }
    public T2 Item2 { get; set; }
}

当然还要用更冗长的方式更改构造函数调用

.Join(context.Test2, q => q.Test11, q => q.Test21,
    (q, p) => new Pair<Test1, Test2> { Item1 = q, Item2 = p }) // <--