我正在尝试通过使用视图模型来清理ASP.NET MVC项目中的操作方法。目前,我的视图模型包含可能与其他实体有关系的实体。例如,ContactViewModel类可能有一个Contact,它可能有一个Address,这两个都是独立的实体。要查询Contact对象列表,我可能会执行以下操作。
IList<Contact> contacts;
using (IContactRepository repository = new ContactRepository())
{
contacts = repository.Fetch().ToList();
}
EditContactViewModel vm = new EditContactViewModel(contacts);
return View(vm);
这种方法带来了一些问题。例如,在using语句中查询存储库。到视图呈现时,上下文已超出范围,使视图无法查询与联系人关联的地址。我可以启用急切加载,但我宁愿不这样做。此外,我不喜欢实体模型已经渗透到我的视野中(我觉得我的视图知道联系人和地址之间的关系是一个坏主意,但我可以不同意我的意见。)
我考虑过创建一个包含Contact和Address实体属性的fattened类。然后我可以将Contact和Address实体投影到我新的扁平对象中。我对这种方法的一个担忧是我的动作方法可能会有点忙碌而我认为 AutoMapper能够将两个或多个对象映射到一个类型中。
克服我的担忧是什么技术首选?
答案 0 :(得分:3)
Automapper适合您的情况。你拥有的是一个对象图,一个东西有更多的东西,Automapper处理得很好。
答案 1 :(得分:1)
按顺序解决这些问题......
首先,如果您担心使用using语句和存储库(我不知道它是LINQ-to-SQL还是LINQ-to-Entities,但它没关系),我会建议你do在Controller上实现IDisposable,然后将存储库存储在模型或控制器中的字段中,或者在视图中可以访问它的位置(如果需要,如果模型知道它,对象是“活着的”然后你只需要在控制器的生命周期中保持它。)
然后,当请求完成时,调用控制器上的Dispose方法,您可以在那里处置存储库。
就个人而言,我的基本控制器类上有一个方法,如下所示:
protected T AddDisposable<T>(T disposable) where T : class, IDisposable
{
// Error checking.
if (disposable == null) throw new ArgumentNullException("disposable");
// Add to list
...
}
基本上,它允许您存储IDisposable实现,然后在控制器的IDisposable实现中,它遍历列表,处理所有内容。
关于地址在实体模型上的曝光,我个人并不认为这是一个流血问题。地址是联系人(IMO)组成的一部分,因此不将其包含在那里是错误的。
但是,如果您不想在那里,我不同意,因为您希望一次只关注一个控制器中的一种类型,等等。
为此,您需要创建数据传输对象,它基本上映射在视图模型中公开的类型与实体模型之间。