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

Nic*_*sen 2 c# automapper entity-framework-6

我正在使用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; }
}
Run Code Online (Sandbox Code Playgroud)

我有这个映射:

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));
Run Code Online (Sandbox Code Playgroud)

每当我运行此代码时:

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

我收到此错误:

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

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

任何帮助表示赞赏:-)

Iva*_*oev 10

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

您可以通过两种方式修复它:

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

public class InventoryLineViewModel
{
    public decimal? Price { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

(B)保持视图模型并更改映射如下:

.ForMember(d => d.Price, o => o.MapFrom(s => ((decimal?)s.InventoryLine.Price) ?? 0))
Run Code Online (Sandbox Code Playgroud)

要么

.ForMember(d => d.Price, o => o.MapFrom(s => s.InventoryLine != null ? s.InventoryLine.Price : 0))
Run Code Online (Sandbox Code Playgroud)


Mik*_*ike 5

.NET 4.0 中,Nullable 有一个“GetValueOrDefault()”方法。因此,如果您将查询转换为 Nullable,那么您可以在完成后得到正确的类型。此方法还将生成正确的单个 SQL SELECT SUM 查询,并且比通过 linq 将整个记录集返回到稍后求和的其他解决方案更快

decimal result = ((decimal?)query.Where(w => w.Customer =="ABC").Sum(s =>  (decimal?)s.Amount)).GetValueOrDefault();
Run Code Online (Sandbox Code Playgroud)