我完全理解这个错误,但有没有办法实现一些代码,以便
linq实体理解我的自定义类型应该被视为十进制基本类型?
我已经创建了一个自定义Money类型,它接受一个构造函数重载的可空小数.它具有隐式运算符重载和所有其他类型的酷爵士乐.我想在我的linq中使用这个自定义类型实体投影,但是标题中的错误.
是否有一个属性,我可以在我的Money类型上声明,“嘿,为了linq投影的目的,我是原始类型十进制”?
是否有某种方式自定义表达式树/访问者可以在这里帮助声明所有类型的Money将被视为linq投影的十进制基元?
[HeyImADecimalForLinqProjections] // custom attribute
public class Money : IComparable<Money>
{
public Money()
{
Value = decimal.Zero;
}
public Money(decimal? value)
{
if (value.HasValue)
Value = value.Value;
else
Value = decimal.Zero;
}
public static implicit operator Money(decimal value)
{
return new Money(value);
}
public static implicit operator Money(decimal? value)
{
return new Money(value.Value);
}
...
}
投影示例:
var items = orderQuery.Where(a => a.OrderId = 345)
.Select(a => new OrderModel()
{
OrderId = a.OrderId,
SubtotalIncludingTax = a.SubtotalIncludingTax, // no dice, SubtotalIncludingTax is of type Money - Unable to cast the type 'System.Decimal' to type 'Money'. LINQ to Entities only supports casting EDM primitive or enumeration types.
SubtotalIncludingTaxRaw = a.SubtotalIncludingTax, // this is fine because SubtotalIncludingTaxRaw is of type decimal
})
.ToList();
我当前的解决方案有效,但我讨厌它.我首先投射到一个匿名类型,然后将匿名类型投影到我的实际模型.这个例子非常淡化,这种双重投影解决方案导致了很多重复,我宁愿避免.
// first get everything as anonymous projection objects in linq to entities
var anonymousItems = orderQuery.Where(a => a.OrderId = 345)
.Select(a =>
{
OrderId = a.OrderId,
SubtotalIncludingTax = a.SubtotalIncludingTax // decimal to decimal
.ToList();
// now cast to our actual model since we are back in .Net world
var items = anonymousItems
.Select(a => new OrderModel()
{
OrderId = a.OrderId,
SubtotalIncludingTax = a.SubtotalIncludingTax // decimal to Money
.ToList();
最佳答案 目前,Entity Framework不支持这样的转换.您可以使用映射属性和未映射的属性进行解决方法,例如:
public decimal RawTotalIncludingTax {get;set;}
public Money TotalIncludingTax
{
get { return RawTotalIncludingtax; }
set { RawTotalIncludingTax = value; }
}
这可能会将额外的匿名类型保存到具体类型选择中,但仍会留下类似的问题.更有可能的解决方案将是一种扩展方法来执行以下操作:
using System;
public static class MoneyExtensions
{
public static string Format(this decimal val){
if(val < 0)
return "(" + Math.Abs(val).ToString("N2") + ")";
else
return val.ToString("N2");
}
}
public class Program
{
public static void Main()
{
Console.WriteLine(2.2m.Format());
Console.WriteLine((-12.42m).Format());
}
}
这样你就不需要自定义类型了,但仍然可以使用你所追求的MoneyExtensions和语法!