如何解决如何使用 Entity Framework Core 3.1 将 ValueObject 的方法转换为 SQL
我有这个值对象
public class ProductReference : ValueObject
{
protected ProductReference(){}
public ProductReference(string value){}
public string Value{get; protected set;}
}
我在我的实体中使用它作为:
public class Product : Entity<long>
{
protected Product(){}
public ProductReference Reference{get; protected set;}
}
在我定义的 OnModelCreating
的 DbContext
中:
modelBuilder.Entity<Product>(entity => {
entity.Property(a => a.Reference)
.HasColumnName("Reference")
.HasConversion(
a => a.Value,s => new ProductReference (s);
});
当我这样做时:
await dbcontext.Products.Where(p=>p.Reference.Value.Contains("some text")).toArrayAsync();
出现异常
表达式无法转换为有效的 sql 语句
我肯定知道有一种方法可以创建自定义表达式转换器,但我找不到一个好的、简单且与 EF Core 3.1 兼容的示例来处理我的问题并清楚地解释了我错过的概念。
我发现这个非常有趣的项目 https://github.com/StevenRasmussen/EFCore.SqlServer.NodaTime 但它太先进了,我无法仅在我的用例中重现它。
[编辑] ValueObject ans Entity 来自 CSharpFunctionalExtensions nuget 包,我认为它们与我的问题无关。
解决方法
首先是关于幕后发生的事情的一些背景信息,以及为什么即使内置简单的转换器(如 BoolToZeroOneConverter
)它也不起作用。
这里的问题是您在转换 new ProductReference(s)
时调用。这是一种方法,您可以在其中做任何想做的事情。例如,如果在 Select
语句中使用它,它将再次失败。例如:
await dbcontext.Products
.Select(x=>new ProductReference(x.Value))
.toArrayAsync();
原因很明显,它将无法翻译。但是为什么它不能将其转换为查询?
因为你正在传递一个构造函数。在这个构造函数中,你可以进行 API 调用或使用反射来为你的对象设置变量,几乎任何东西。这当然不能在 SQL 查询中进行翻译。
转换器通常用于内存中,但它们也可用于数据库操作。这意味着您将需要这样的东西:
await dbcontext.Products
.Select(x=>new ProductReference() // empty constructor that does nothing
{
Property1 = x.Property1 // I don't know how the constructor maps them
})
.toArrayAsync();
使用这种类型的表达式允许您将表达式实际转换为 SQL 语句,而不是在 SQL DB 上而不是在内存中进行转换。
现在在您的特定情况下使用:
.HasConversion(
a => a.Value,s => new ProductReference (){};
});
应该可以解决您的问题,但我不明白您为什么要将 ProductReference
初始化或转换为 ProductReference
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。