实体框架6
我有一个代表 Id 的类型:
public readonly record struct Id
{
public Id(int intValue)
{
if (intValue <= 0)
throw new InvalidIdException();
IntValue = intValue;
}
public static explicit operator int(Id id) => id.IntValue;
public static explicit operator Id(int id) => new(id);
public int IntValue { get; }
public override string ToString()
{
return IntValue.ToString();
}
}
我还有一个扩展方法:
public static class IdHelper
{
public static Id ToId(this int id)
{
return (Id) id;
}
}
Order 有一个 DTO 类型:
public class Order {
public Id OrderId {get;set;}
public string OrderDesc {get;set;}
}
我想执行这样的查询:
var order = db.Orders.Select(x => new Order() { OrderId = x.order_id.ToId(), OrderDesc = x.order_desc });
它不起作用,因为 EF6 既不能翻译
ToId()
,也不能翻译 (Id)x.order_id
,也不能翻译 new Id(x.order_id)
。
我当然可以写:
var order = db.Orders.Select(x => new { x.order_id, x.order_desc }).ToList().Select(x => new Order() { OrderId = x.order_id.ToId(), OrderDesc = x.order_desc });
但是由于 DTO 有时可能很大,我想减少不必要的代码量和使用的内存(理想情况下我希望结果中有
List
而不是 WhereSelectListIterator
)
是否可以编写一些
ExpressionVisitor
或自定义 QueryProvider
来处理 ToId()
或在结果 Id
中显式转换为 Select
?
您实际上不需要任何复杂的表达式,相反,您可以依靠 C# 运算符来为您完成这项工作。您已经定义了
explicit
运算符,这意味着您可以简单地执行以下操作:
var order = db.Orders
.Select(x => new Order
{
OrderId = (Id)x.order_id,
OrderDesc = x.order_desc
});
或者,如果您将
explicit
更改为 implicit
,您可以完全放弃演员表:
var order = db.Orders
.Select(x => new Order
{
OrderId = x.order_id,
OrderDesc = x.order_desc
});