ASP.NET MVC /实体框架:通过聚合根存储库访问聚合对象

时间:2010-08-05 18:10:58

标签: asp.net-mvc entity-framework aggregateroot

我正在使用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>

我知道我还有很多需要学习的东西,所以希望你能指出我正确的方向!

谢谢!

2 个答案:

答案 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
}

我认为,对于您的SQLCustomersRepositoryFakeCustomersRepository实施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,那么你应该有一个单独的存储库。