我正在尝试将我的MVC3项目分离成适当的DAL/Domain/ViewModel架构,但是我在使用AutoMapper从域映射到视图模型时遇到了一个问题,即如何映射计算字段。
以下是我尝试做的示例:
接口
public interface IRequirement
{
int Id { get; set; }
... bunch of others
public decimal PlanOct { get; set; }
public decimal PlanNov { get; set; }
public decimal PlanDec { get; set; }
... and so on
decimal PlanQ1 { get; }
... etc
decimal PlanYear { get; }
... repeat for ActualOct, ActualNov ... ActualQ1 ... ActualYear...
}
Domain Model
public class Requirement : IRequirement
{
public int Id { get; set; }
... bunch of others
public decimal PlanOct { get; set; }
public decimal PlanNov { get; set; }
public decimal PlanDec { get; set; }
... and so on
public decimal PlanQ1 { get { return PlanOct + PlanNov + PlanDec; } }
... etc
public decimal PlanYear { get { return PlanQ1 + PlanQ2 + PlanQ3 + PlanQ4; } }
... repeat for ActualOct, ActualNov ... ActualQ1 ... ActualYear...
}
还有VarianceX属性,例如计算公式为(PlanOct - ActualOct)的VarianceOct等。
我的视图模型几乎与上述内容相同,只是使用默认的getter/setter语法而非计算字段,例如:
public decimal PlanQ1 { get; set; }
我的Global.asax中的AutoMapper配置如下:
Mapper.CreateMap<Domain.Abstract.IRequirement, Models.Requirement.Details>();
这在所有属性上运行良好,除了计算属性。我的所有计算字段(即*Q1、*Q2、*Q3、*Q4、*Year和所有Variance*字段)实际上都没有映射 - 它们都显示默认值0.00。
我对此感到困惑,并且我也是AutoMapper的新手,所以也许我错过了什么。我的直觉是,由于属性签名不相同(即域对象只有非默认getter而没有setter,而视图模型具有默认getter和setter),因此AutoMapper没有将其选中。但我还做了这个:
Mapper.CreateMap<Domain.Abstract.IRequirement, Models.Requirement.Details>()
.ForMember(dest => dest.PlanQ1, opt => opt.MapFrom(src => src.PlanQ1);
并且计算结果仍然是0。我在调试器中进行了确认。
我做错了什么?
先谢谢你。
编辑1
在遵循Wal的建议后,我运行了测试,它可以正常工作,所以我一步一步地回溯,首先将Field1 / Field2 / Field3部分粘贴到接口/域/视图模型类中,并验证其在我的控制器中是否有效,然后逐一更改。我发现,由于我处理的是十进制类型,如果我硬编码为整数或双精度值,则会得到零,但如果我强制转换为十进制或使用十进制文字,则可以正常工作。但是,只有在我手动设置它们时才有效,而不是从数据库中提取值时。
换句话说,这个可以工作(即PlanQ1 = 6):
var D = new Requirement { PlanOct = (decimal) 1.0, PlanNov = (decimal) 2.0, PlanDec = (decimal) 3.0 };
var V = Mapper.Map<IRequirement, Details>(D);
这是可行的:
var D = new Requirement { PlanOct = 1M, PlanNov = 2M, PlanDec = 3M };
var V = Mapper.Map<IRequirement, Details>(D);
但这并不是(从存储库对象中提取单个域对象,进而使用Entity Framework从SQL Server中提取):
var D = requirementRepository.Requirement(5);
var V = Mapper.Map<IRequirement, Details>(D);
在上述情况下,我得到的计划Q1和计划年份都是0。我已经验证了域对象(D)中的PlanOct = 1、PlanNov = 2和PlanDec = 3。我还验证了所有对象的类型,包括EF生成的对象,都是十进制数,并且SQL Server类型也是十进制数。甚至我尝试将其映射到创建的视图模型,以排除错误,但仍然得到了计划Q1和计划年份为0的结果:
var D = requirementRepository.Requirement(5);
var V = new Details();
Mapper.Map<IRequirement, Details>(D, V);