转换为值类型失败,因为实现值为null

时间:2016-12-14 18:37:38

标签: c# entity-framework-6 automapper

我正在使用AutoMapper将我的实体投影到模型。

这些是我映射到的模型:

public partial class Material
{
    public System.Guid Id { get; set; }
    public string Description { get; set; }
    public string EAN { get; set; }

    public virtual InventoryLine InventoryLine { get; set; }
}

public partial class InventoryLine
{
    public System.Guid MaterialId { get; set; }
    public Nullable<decimal> Quantity { get; set; }
    public decimal Price { get; set; }
    public Nullable<System.DateTime> LastInspectionDate { get; set; }
    public int TransactionsSinceLastInspection { get; set; }

    public virtual Material Material { get; set; }
}

public class InventoryLineViewModel
{
    public string EAN { get; set; }
    public string Description { get; set; }
    public decimal Price { get; set; }
    public decimal? Quantity { get; set; }
    public DateTime? LastInspectionDate { get; set; }
}

我有这个映射:

CreateMap<Material, InventoryLineViewModel>().ForMember(d => d.Price, o => o.MapFrom(s => s.InventoryLine.Price)).ForMember(d => d.Quantity, o => o.MapFrom(s => s.InventoryLine.Quantity)).ForMember(d => d.LastInspectionDate, o => o.MapFrom(s => s.InventoryLine.LastInspectionDate));

每当我运行此代码时:

Mapper.Initialize(c => { c.AddProfile(new MapperProfile()); });
return context.Material.Include(i => i.InventoryLine).ProjectTo<InventoryLineViewModel>().ToList();

我收到此错误:

  

转换为值类型'System.Decimal'失败,因为具体化值为null。结果类型的泛型参数或查询必须使用可空类型。

当我映射到的所有类型具有相同的数据类型时,这怎么可能?我甚至尝试在数据库和视图模型中使Quantity属性不可为空。我仍然得到同样的错误。

感谢任何帮助: - )

3 个答案:

答案 0 :(得分:9)

问题是视图模型Price属性类型不可为空,但由于源InventoryLine是可选的,因此EF(如异常消息中所建议的)需要能够存储可空的来源为null时的值。

您可以通过两种方式解决问题:

(A)使视图模型属性可为空:

public class InventoryLineViewModel
{
    public decimal? Price { get; set; }
}

(B)保留视图模型并按如下方式更改映射:

.ForMember(d => d.Price, o => o.MapFrom(s => ((decimal?)s.InventoryLine.Price) ?? 0))

.ForMember(d => d.Price, o => o.MapFrom(s => s.InventoryLine != null ? s.InventoryLine.Price : 0))

答案 1 :(得分:3)

.NET 4.0,Nullable具有“ GetValueOrDefault()”方法。 因此,如果将查询强制转换为Nullable,则完成后可以得到正确的Type。 此方法还将生成正确的单个SQL SELECT SUM查询,并且比通过linq将整个记录集返回到更高的总和的其他解决方案要快。

decimal result = ((decimal?)query.Where(w => w.Customer =="ABC").Sum(s =>  (decimal?)s.Amount)).GetValueOrDefault();

答案 2 :(得分:-1)

致电.ToList()为我解决了此错误。