C# Sql树错误中OrderBy、ThenBy和Null类型映射的重新实现
我试图以不同的方式实现C# Sql树错误中OrderBy、ThenBy和Null类型映射的重新实现,c#,linq,lambda,entity-framework-core,expression-trees,C#,Linq,Lambda,Entity Framework Core,Expression Trees,我试图以不同的方式实现OrderBy和ThenBy来隐藏OrderBy和ThenBy扩展方法中的lambda表达式。这些扩展方法接受实现IOrderSpecification的类: public class PersonOrderByAgeSpecification : OrderSpecification<Person> { public PersonOrderByAgeSpecification(Sort direction= Sort.Ascending) : base
OrderBy
和ThenBy
来隐藏OrderBy
和ThenBy
扩展方法中的lambda表达式。这些扩展方法接受实现IOrderSpecification
的类:
public class PersonOrderByAgeSpecification : OrderSpecification<Person>
{
public PersonOrderByAgeSpecification(Sort direction= Sort.Ascending) : base(direction)
{
}
public override Expression<Func<Person, IComparable>> AsExpression()
{
return personOrder => personOrder.Age;
}
}
当AsExpression()
中的属性类型只是字符串时,它可以正常工作。例如:
public override Expression<Func<Person, IComparable>> AsExpression()
{
return personOrder => personOrder.FirstName;
}
public重写表达式AsExpression()
{
return personOrder=>personOrder.FirstName;
}
否则,我将得到以下错误:(不适用于integer或bool)
InvalidOperationException:Sql树中的Null类型映射
Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.RelationalSqlTranslatingExpressionVisitor+SqlTypeMappingVerifyingExpressionVisitor.VisitExtension(表达式
节点)
源代码是可用的
非常感谢您的帮助。首先,您使用的是预览(测试版)软件,预计会出现问题 但主要的问题是LINQ排序方法有第二个泛型类型参数
TKey
,您将其隐藏在IComparable
后面,对于值类型,它会在表达式中导致隐藏强制转换
除了不必要的装箱之外,这对于LINQ to Objects provider来说不是问题,因为它只是编译并执行来自lambda表达式的委托。但是,其他IQueryable
提供程序通常需要将表达式转换为其他内容(通常是SQL)。它们中的大多数识别此类强制转换(Expression.Convert
),并在处理过程中删除它们。显然,您正在使用的EF3.0预览版没有,因此出现了异常
您可以通过自己消除隐藏的强制转换来避免此类问题。通过表达式操纵可以做到这一点,但最简单的方法是将第二个泛型类型参数引入基础抽象类:
public abstract class OrderSpecification<T, TKey> : IOrderSpecification<T>
一切都会好起来。你可能以前测试过这个,但我-以防万一-用我编的
列表测试了它,对照字符串,int
和bool
排序,所有这些都很好。您似乎遇到了EFCore的RelationalSqlTranslatingExpressionVisitor的一个问题,可以在这里找到:您可能想打开一个新问题。我也这么认为。现在我正在使用Microsoft.EntityFrameworkCore版本3.0.0-preview3.19153.1。我在Microsoft.EntityFrameworkCore 2.X.X上没有经历过同样的事情。
public abstract class OrderSpecification<T, TKey> : IOrderSpecification<T>
public abstract Expression<Func<T, TKey>> AsExpression();
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
public class PersonAgeOrderSpecification : OrderSpecification<Person, int>
{
public PersonAgeOrderSpecification(Sort direction) : base(direction) { }
public override Expression<Func<Person, int>> AsExpression()
{
return person => person.Age;
}
}