我完全卡住了。
我有两个控制器:"客户"和"地址"。两者都有字段CustomerRepository和AddressRepository。
有两个ViewModel:CustomerViewModel和AddressViewModel。它们还具有CustomerRepository和AddressRepository字段。 (还有一个无参数构造函数,因为它们是编辑和创建方法中的参数)
存储库本身具有来自我的实体的DbContext对象。
现在我遇到了一个接一个的问题。我想我应该只有一个DbContext与我的所有类共享(Repositories和ViewModels)。我认为UnitOfWork是解决方案。但我不知道如何使用它。
我目前尝试在控制器构造函数中创建一个DbContext,并将其传递给需要它的每个对象。但即使这样也行不通。
如果需要代码,我会发布。
答案 0 :(得分:4)
要了解的事情:
工作单元不一定是IUnitOfWork
的某种实施方式。它只是一种可能以多种方式应用的模式。首先,最重要的是 - 在实际使用它之前你应该理解它是什么,并使周围的事情过于复杂。此外,EF Code-First DbContext API的DbContext
是一种Unit of Work
模式。您的IDbSet<>
是您的存储库。不要试图从你的ORM中抽象出来,从最简单的事情开始。
首先,只需使用构造函数注入将DbContext注入Controller。不要忘记设置所选的IoC容器并连接MVC的DependencyResolver
。您的控制器可能看起来像(示例还包含AutoMapper用法示例,请参阅有关ViewModels的下一点):
public CustomerController : Controller
{
public CustomerController(MyDbContext data, IMappingEngine mapper)
{
Data = data;
Mapper = mapper;
}
public MyDbContext Data { get; set; }
public IMappingEngine Mapper { get; set; }
// Other controller code
}
这又是一个易于实现的模式 - 只需使用CustomerViewModel
并使用AutoMapper即可轻松将Customer
转换为CustomerViewModel
,以便您可以这样做:
public ActionResult Details(int id)
{
var customer = Data.Customers.FirstOrDefault(c => c.Id == id);
if (customer == null)
return new HttpNotFoundResult();
return View(Mapper.Map<CustomerViewModel>(customer));
}
您可以询问AutoMapper的网站,了解如何连接并使其运行。 请注意,您没有直接从DbContext获取ViewModel。您获得一个“实体”,然后转换为适当的视图模型。
希望这有帮助!
答案 1 :(得分:2)
您的ViewModel不应该引用DbContext或存储库。 ViewModels应该是非常愚蠢的。控制器(或控制器调用的服务)的工作是使用View所需的数据填充ViewModel。
工作单位是一个很好的模式,你应该使用它...但是patern不能解决你的问题。您的问题是您的视图对数据模型的了解太多。
答案 2 :(得分:0)
我目前正在执行以下操作: 一个注入IUnitOfWork使用unity注入我的控制器。
IUnitOfWork实现了IContext。
IContext包含IDbSet Customers和IDbSet IContext的具体实现实现了DbContext。
我的控制器引用服务,该服务使用IUnitOfWork。 如果您使用存储库,那么只需使用注入控制器的单个IContext(或IUnitOfWork,它很容易添加到顶部)
这样我在请求的每个生命周期中都有一个上下文,然后它被处理掉了。如果你想要更多代码,请告诉我,我会看到我可以在这里发布的内容。