ASP。 NET MVC:将实体映射到视图模型
我正在尝试通过使用视图模型来清理 ASP.NET MVC 项目中的操作方法。目前,我的视图模型包含可能与其他实体有关系的实体。例如,ContactViewModel 类可能有一个联系人,它可能有一个地址,两者都是单独的实体。要查询 Contact 对象的列表,我可能会执行如下操作。
IList<Contact> contacts;
using (IContactRepository repository = new ContactRepository())
{
contacts = repository.Fetch().ToList();
}
EditContactViewModel vm = new EditContactViewModel(contacts);
return View(vm);
这种方法带来了一些问题。例如,在 using 语句中查询存储库。当视图呈现时,上下文已经超出范围,使得视图无法查询与联系人关联的地址。我可以启用急切加载,但我不愿意。此外,我不喜欢实体模型渗透到我的视图中(我觉得让我的视图了解联系人和地址之间的关系是一个坏主意,但请随意不同意我的观点)。
我考虑过创建一个包含联系人和地址实体属性的扩展类。然后,我可以将联系人和地址实体投影到新的扁平对象中。我对这种方法的担忧之一是我的操作方法可能会变得有点繁忙,并且我不认为 AutoMapper 能够将两个或多个对象映射到单一类型。
为了克服我的担忧,首选什么技术?
I'm trying to clean up my action methods in an ASP.NET MVC project by making use of view models. Currently, my view models contain entities that might have relationships with other entities. For example, ContactViewModel class might have a Contact, which might have an Address, both of which are separate entities. To query for a list of Contact objects, I might do something like the following.
IList<Contact> contacts;
using (IContactRepository repository = new ContactRepository())
{
contacts = repository.Fetch().ToList();
}
EditContactViewModel vm = new EditContactViewModel(contacts);
return View(vm);
This method brings on a few problems. For example, the repository is queried within a using statement. By the time the view renders, the context has gone out of scope, making it impossible for the view to query the Address associated with the Contact. I could enable eager loading, but I'd rather not. Furthermore, I don't like that the entity model has bled over into my view (I feel like it's a bad idea for my View to have knowledge of the relationship between Contact and Address, but feel free to disagree with me).
I have considered creating a fattened class that contains properties from both the Contact and Address entities. I could then project the Contact and Address entities into my new, flattened object. One of my concerns with this approach is that my action methods may get a little busy and I don't think AutoMapper is able to map two or more objects into a single type.
What technique is/are preferred for overcoming my concerns?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Automapper 将适合您的情况。你拥有的是一个对象图,一个事物有更多的事物,Automapper 可以很好地处理。
Automapper will work for your case. What you have is an object graph, a thing has some more things, which Automapper handles fine.
按顺序考虑这些问题...
首先,如果您担心 using 语句和存储库(我不知道它是 LINQ-to-SQL 还是 LINQ-to-Entities,但这并不重要),我建议你做的是在你的控制器上实现 IDisposable ,然后将存储库存储在模型上或控制器上的字段中或你可以在视图中访问它的某个地方(如果你需要它,如果模型有当对象“活着”时知道它,那么你只需要在控制器的生命周期内保留它)。
然后,当请求完成时,将调用控制器上的 Dispose 方法,您可以在那里处置存储库。
就我个人而言,我的基本控制器类上有一个方法,如下所示:
基本上,它允许您存储 IDisposable 实现,然后在控制器的 IDisposable 实现中,它迭代列表,处理所有内容。
关于实体模型上地址的暴露,我个人不认为这是一个出血问题。地址是联系人组成的一部分 (IMO),因此不将其放在那里是错误的。
但是,如果您不希望它在那里,我并不反对,因为您想一次专注于一个控制器中的一种类型,等等。
为此,您需要创建基本上映射于之间的数据传输对象您在视图模型和实体模型中公开的类型。
Taking these concerns in order...
First, if you are worried about the using statement and the repository (I don't know if it is LINQ-to-SQL or LINQ-to-Entities, but it doesn't matter), what I would recommend you do is implement IDisposable on your Controller, and then store the repository in a field either on the model or in the controller or somewhere where you have access to it in the view (if you need it, if the model has knowledge of it while the object is "alive" then you just need to keep it around for the life of the controller).
Then, when the request is complete, the Dispose method on your controller is called and you can dispose of the repository there.
Personally, I have a method on my base controller class which looks like this:
Basically, it allows you to store the IDisposable implementations, then in the IDisposable implementation of the controller, it iterates through the list, disposing of everything.
Regarding the exposure of the address on the entity model, I don't see this as a bleed issue, personally. The address is part of the composition of the contact (IMO), so it would be wrong to not have it there.
However, I don't disagree if you don't want it there because you want to focus on one type in one controller at a time, etc, etc.
To that end, you would want to create Data Transfer Objects which basically map between the type you expose in the view model and your entity model.