我正在使用ASP.NET MVC 2和Entity Framework构建我的第一个Web应用程序。我正在使用存储库模式。根据我在Stack Overflow和其他网站上收集的信息,似乎共识是每个域模型对象有一个控制器,每个聚合根对象有一个存储库。
我的问题是我应该如何通过聚合根存储库访问非根聚合对象。在我正在处理的示例中,有一个Customer模型和一个Boat模型。小船只能存在对客户的FK引用,并且只需要在客户的上下文中引用小船。这让我相信我有这两个对象的聚合,而客户是根。
现在在我的Boats控制器中,我有一个Edit动作方法:
public class BoatsController : Controller
{
private ICustomersRepository customersRepository;
public BoatsController(ICustomersRepository customersRepository)
{
this.customersRepository = customersRepository;
}
public JsonResult Edit(int id, FormCollection collection)
{
var boat = customersRepository.GetBoat(id);
// Update boat
}
}
我的问题是如何在存储库中检索Boat对象?
public class SQLCustomersRepository : ICustomersRepository
{
DatabaseEntities db = new DatabaseEntities();
public Boat GetBoat(int id)
{
return db.Boats.SingleOrDefault(x => x.ID == id);
// OR
return db.Customers.Where(x => x.Boats.Any(y => y.ID == id)
.Select(x => x.Boats.FirstOrDefault(y => y.ID == id);
}
}
我可以从Customers Repository引用db.Boats吗?它似乎是最干净的,但这意味着我必须改变我的FakeCustomersRepository以获得客户和船只列表。
通过db.Customers访问Boat似乎更合理,但我无法弄清楚如何返回单个Boat对象而不在LINQ查询中重复自己。这对我来说并不合适。< / p>
我知道我还有很多需要学习的东西,所以希望你能指出我正确的方向!
谢谢!
答案 0 :(得分:1)
在我看来,您正在讨论实现细节,而不是您的抽象接口和模型。您的界面看起来像这样:
public interface ICustomersRepository
{
//... other methods
Boat GetBoat(int id);
//... other methods
}
和这样的模型:
public class Customer
{
//... other stuff
ICollection<Boat> Boats; // or another collection type
//... other stuff
}
我认为,对于您的SQLCustomersRepository
和FakeCustomersRepository
实施ICustomerRepository完全不同的任何设计规则并没有反对任何设计规则,并且找到与您的基础数据存储相关的最佳实现
由于您似乎在SQL-DB的Boat表上有一个主键,我肯定会利用这个并实现第一个选项:return db.Boats.SingleOrDefault(x => x.ID == id);
但是你的FakeCustomersRepository
没有必要收集船只。如果您更容易获得客户列表并使用测试船填充每个客户的Boats集合,为什么不呢?在这种情况下,GetBoat
中的FakeCustomersRepository
实现可以使用您描述的第二个LINQ查询来实现。
请记住,MVC中的单元测试并不打算测试您的特定Repository实现,而是测试您的业务逻辑,而业务操作更像是各种域对象和存储库方法调用的链。如果单个存储库方法执行它应该执行的操作(例如,如果GetBoat
确实返回具有正确ID的船),则更多的是稍后的集成测试以证明您的数据库调用正常工作。
答案 1 :(得分:0)
为什么你没有船库?
如果Boat是一个AggRoot,那么你应该有一个单独的存储库。