如何使用具体类型(又名 "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 }) // <--
我正在尝试进行连接然后过滤结果:
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 }) // <--