c# - EF Core 是否可以在针对具有转换的属性的查询中调用方法?

标签 c# sql sql-server entity-framework entity-framework-core

假设我想增强一个模型

public class Person
{
    public string Name { get; set; }
    public string Address { get; set; }
}
所以我为 Address 使用了一个复杂的对象:
public class Person
{
    public string Name { get; set; }
    public Address Address { get; set; }
}
EF Core 非常好地通过 HasConversion 实现了这一点。特征:
modelBuilder.Entity<Person>
            .Property(p => p.Address)
            .HasConversion(addr => addr.ToString(), str => Address.FromString(str));
我什至测试过,这适用于 == 的查询运算符:以下将成功转换为 SQL
var whiteHouse = Address.Parse("1600 Pennsylvania Avenue NW");
var matches = from person in people 
              where person.Address == whiteHouse 
              select person;
但是,假设我想 string.Containsstring Address 的版本, 就像是
var search = "1600";
var matches = from person in people 
              where person.Address.ToString().Contains(search) 
              select person;
这将无法转换。 EF Core 是否有任何功能可以映射 ToString()方法或以其他方式映射转换为 string 的复杂对象/VARCHAR以便我可以编写这样的查询?

最佳答案

EF Core 值转换器和 LINQ 查询的问题在于 LINQ 查询针对 CLR 实体属性,因此是 CLR 类型而不是提供程序类型。目前在 Limitations 下部分提到了这一点EF Core 文档的值(value)转换系统部分:

Use of value conversions may impact the ability of EF Core to translate expressions to SQL. A warning will be logged for such cases. Removal of these limitations is being considered for a future release.


因此,针对 CLR 类型的查询表达式加上无法翻译自定义方法会导致您的问题。从技术上讲,可以添加自定义方法/属性转换,但它非常复杂,因为需要大量非用户友好的基础设施管道代码,这使得在现实生活应用程序开发中几乎无法使用。
但在这种特殊情况下,您知道提供程序类型是 string , 数据库表值由 ToString 生成方法。所以你只需要让查询使用提供者类型。你可以通过使用 cast 运算符来做到这一点。
通常,如果已知对象类型之间没有转换,C# 编译器将不允许您将已知对象类型转换为另一个已知对象类型。但是您可以使用“双重转换”技术来欺骗它,首先将其转换为 object。然后到所需的类型。幸运的是,EF Core 转换器支持这种类型转换,并正确地(某种程度上)将它们转换为 SQL。我的意思是它发出不必要的(冗余)CAST在查询内部,但至少它翻译并执行服务器端。
话虽如此,您的示例的解决方案是
where ((string)(object)person.Address).Contains(search)

关于c# - EF Core 是否可以在针对具有转换的属性的查询中调用方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63856189/

相关文章:

sql - SQL 绑定(bind)参数会影响性能吗?

javascript - 从 Jquery 获取 Json 列表

asp.net - 无法打开登录请求的数据库 "ASPNETDB"。登录失败。用户 'Philip-Desktop\Philip' 登录失败

SQL Server 时间与午夜以上时间的比较

sql-server - 如何根据隔离级别读取原始数据

sql - 如何将 .sql 文件加载到 Scala?

c# - ASP.net WebApi 发现与 URL 匹配的多个 Controller 类型

c# - 如何开发 Dicom 网页查看器

c# - ImageAnimator.StopAnimate() 似乎没有实际执行任何操作

SQL - 获取最大值