假设我想增强一个模型
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));
我什至测试过,这适用于 ==
的查询运算符:以下将成功转换为 SQLvar whiteHouse = Address.Parse("1600 Pennsylvania Avenue NW");
var matches = from person in people
where person.Address == whiteHouse
select person;
但是,假设我想 string.Contains
在 string
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/