存储库模式,ViewModel和ORM

时间:2012-06-29 12:48:43

标签: orm viewmodel repository-pattern dto

使用Repository模式和ViewModel,如果您不希望原始数据库对象泄漏到存储库之外,如何针对数据库构建查询?如何在不加载内存中的所有数据库并使用LINQ to Objects的情况下实际创建查询?我无法将IQueryable暴露给应用程序的其余部分。

例如,使用EF我有一堆POCO,它们具有与db字段匹配的几个属性,但也有一些东西可以解决枚举不能直接支持(现在)以及外键ID来防止N + 1和更容易查询等。我不希望它们泄漏到应用程序的其余部分,我希望应用程序只看到一个普通的对象图。

public class DbUser
{
    public int Id { get; set; }
    public string Name { get set; }

    public int GroupId { get; set; }
    public DbGroup Group { get; set; }

    public ICollection<DbComment> { get; set; }
}

public class User
{
    public int Id { get; set; }
    public string Name { get set; }

    public Group Group { get; set; }
    public ICollection<Comment> { get; set; }
}

这里的问题是我的存储库将在内部使用EF进行查询(以及单元测试时的内存中)。但是我该如何实施IQueryable<User> FindAll()?我不能只返回dbContext.Users.Select(u => new User(u)),因为在这种情况下我失去了所有可能的查询能力;它只是将整个用户集合加载到内存中,将所有类型从DbUser转换为User,然后在内存集合中构建LINQ查询 - 这非常低效。

我不能只在存储库中构建查询。在某些页面上,我有查询选择几个字段,但也从其他相关对象计算一些复杂的东西,根据结果过滤它们(例如带有正分数的评论计数),但我还需要在应用程序中。我可以选择用于获取复杂内容的所有对象并将它们返回给应用程序(但不是作为数据库实体),但这意味着选择大量数据。

基本上,我如何阻止数据库实体以其残留和黑客攻击应用程序的其余部分,同时仍然保持在存储库之外构建查询的能力

1 个答案:

答案 0 :(得分:1)

CQRS(Command Query Responsibility Segregation)解决了这个问题。你有'真实'模型,域模型,所有业务规则和所有这些,以及一个'query-ony'模型,它基本上是一个简单的poco(可以由Views直接使用),它将由一个专门的查询存储库。

持久性模型(EF实体)仅用于与db“交谈”,repos始终返回或处理域/应用程序对象。基本上,您必须将EF实体映射到域实体(并且在保存时反之亦然)。通过这种方式,您将拥有各自独立的模型。