我正在将ASP.NET MVC 3与Raven DB用作后备数据存储.我有一组模型,我有兴趣将其转换为ViewModels.为此,我利用AutoMapper来完成将每个属性映射到ViewModel中对应属性的工作.假设我有一个像这样的模型:
public class FooModel
{
public int Id { get; set; }
public string Name { get; set; }
public int AlphaId { get; set; }
public int BetaId { get; set; }
}
然后假设我要将其转换为如下所示的ViewModel:
public class FooViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public int AlphaId { get; set; }
public Alpha Alpha { get; set; }
public int BetaId { get; set; }
public Beta Beta { get; set; }
}
然后,在应用启动时按如下方式设置我的地图:
Mapper.CreateMap<Foo, FooViewModel>();
然后,在控制器中,我按如下方式执行地图:
public ActionResult FooDetails(string id)
{
using(var session = this.documentStore.OpenSession())
{
var fooInstance = session.Load<Foo>(id);
var fooViewModel = Mapper.Map<FooViewModel>(fooInstance);
return this.View(fooViewModel);
}
}
问题是,如您在上面看到的那样,从存储库出来的实体具有2个属性,这些属性是其他对象的键,类型为Alpha和Beta.我对基于AlphaId和BetaId键的Alpha和Beta保湿非常感兴趣.
起初我以为我会利用AutoMapper的自定义转换功能,但是鉴于我们需要将数据会话注入到映射中(调用数据存储以检索Alpha或Beta对象),因此我认为这种方法不起作用. .
另一种选择是仅执行控制器动作中的所有工作,但是很快就会变得笨拙(在给出的特定示例中不是,但这仅是说明这一点的示例).
Alpha和Beta的水合应该在哪里发生,这里有什么好的模式?
解决方法:
这可能并不理想,但是您是否可以不只是为两个引用创建映射并在事实之后映射它们.您仍然必须分别调用它们,但要让AutoMapper进行繁重的映射,而不是用自己的映射填充控制器.
public ActionResult FooDetails(string id)
{
using(var session = this.documentStore.OpenSession())
{
var foo = session.Load<Foo>(id).Include(....);
var alpha = session.Load<Alpha>(foo.AlphaId);
var beta = session.Load<Beta>(foo.BetaId);
// null checks
var fooViewModel = Mapper.Map<FooViewModel>(foo);
fooViewModel.Alpha = Mapper.Map<AlphaViewModel>(alpha);
fooViewModel.Beta = Mapper.Map<BetaViewModel>(beta);
return View(fooViewModel);
}
}
我还没有太多使用AutoMapper,但是也许您可以通过Map函数传入子对象(以在CreateMap上提供ForMember链)?也许Alexandre的AfterMap建议可能有用,但我看不到如何在没有在控制器动作内部创建地图的情况下给“被引用”的孩子补水(但是您也可以直接使用ForMember和Raven会话,并且只使用一个Mapper.Map).
另外-AutoMapper文档为嵌套/子映射建议了类似的方法-https://github.com/AutoMapper/AutoMapper/wiki/Nested-mappings.尽管它更类似于对象引用,而不是对象ID引用的情况.
我无法评论其他答案,但是关于Pavel的答案-您不是真的以这种方式使用Raven,没有o / r映射(内部JSON->对象除外)或数据访问层,您只需直接使用Raven会话(也许通过服务即可,但是当然不需要存储库或类似的东西).关于引用,字节是正确的,正如他在其他答案之一中所评论的那样,最好的方法是存储id引用并使用Raven包含-它的结果相同,仍然仅使用一个请求.