存储库模式、视图模型和ORMs

存储库模式、视图模型和ORMs,orm,viewmodel,repository-pattern,dto,Orm,Viewmodel,Repository Pattern,Dto,使用Repository pattern和ViewModels,如果不希望原始数据库对象泄漏到存储库之外,如何针对数据库构建查询?如何在不将所有数据库加载到内存中并使用LINQ to对象的情况下创建查询?我无法向应用程序的其余部分公开IQueryable 例如,有了EF,我就有了一堆POCO,其中有几个属性与db字段匹配,但也有一些东西需要解决(目前)不直接支持的枚举以及防止N+1的外键ID和更简单的查询等问题。我不希望它们泄漏到应用程序的其余部分,我希望应用程序只看到一个普通的对象图 publ

使用Repository pattern和ViewModels,如果不希望原始数据库对象泄漏到存储库之外,如何针对数据库构建查询?如何在不将所有数据库加载到内存中并使用LINQ to对象的情况下创建查询?我无法向应用程序的其余部分公开IQueryable

例如,有了EF,我就有了一堆POCO,其中有几个属性与db字段匹配,但也有一些东西需要解决(目前)不直接支持的枚举以及防止N+1的外键ID和更简单的查询等问题。我不希望它们泄漏到应用程序的其余部分,我希望应用程序只看到一个普通的对象图

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; }
}
公共类DbUser
{
公共int Id{get;set;}
公共字符串名称{get set;}
public int GroupId{get;set;}
公共数据库组{get;set;}
公共ICollection{get;set;}
}
公共类用户
{
公共int Id{get;set;}
公共字符串名称{get set;}
公共组组{get;set;}
公共ICollection{get;set;}
}
这里的问题是,我的存储库将在内部使用EF进行查询(以及在单元测试时使用内存中的东西)。但是如何实现
IQueryable FindAll()
?我不能只返回
dbContext.Users.Select(u=>newuser(u))
,因为在这种情况下,我将失去所有可能的查询能力;它只需在内存中加载整个用户集合,将所有类型从DbUser转换为user,然后在内存集合上构建LINQ查询,这是非常低效的

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

基本上,我如何防止数据库实体污染应用程序的其余部分,同时保持在存储库之外构建查询的能力?

CQRS(命令查询责任分离)解决了这个问题。您有“真实”模型、域模型以及所有业务规则等,还有“查询ony”模型,基本上是一个简单的poco(可由视图直接使用),将由专门的仅查询存储库返回


peristence模型(EF实体)仅用于与db“对话”,REPO始终返回或处理域/应用程序对象。基本上,您必须将EF实体映射到域实体(保存时反之亦然)。通过这种方式,您将拥有独立的模型,每个模型都有自己的用途。

特别是我使用的是实体框架,其DbContext和DbSet实现了存储库和工作单元;我应该在测试期间使用EF实体作为模型并模拟上下文和集合吗?这就是我倾向于的。