Entity framework 无存储库的实体框架中的可重用查询。怎么用?

Entity framework 无存储库的实体框架中的可重用查询。怎么用?,entity-framework,repository-pattern,unit-of-work,Entity Framework,Repository Pattern,Unit Of Work,让我说,我已经得出结论(经过大量的试验),当使用实体框架时,存储库和工作单元是错误的,错误的,错误的,而且非常好 但我真的很讨厌那些嵌入式查询。问题是,如果我如此反对存储库,我可以把它们放在哪里呢?(请回答清楚,非常感谢示例) 我刚刚取消了两个包含我的存储库、工作单元和数百个文件的接口的项目,因为没有看到回报。我想很多人,包括我自己,都加入了存储库的行列,因为其他人都在这么做,但回想起来,我认为这真的是一次无路可走的旅程 /叹息 理查德你想把它们放在哪里?您只有很少的选择: 让它们保持原样,并使

让我说,我已经得出结论(经过大量的试验),当使用实体框架时,存储库和工作单元是错误的,错误的,错误的,而且非常好

但我真的很讨厌那些嵌入式查询。问题是,如果我如此反对存储库,我可以把它们放在哪里呢?(请回答清楚,非常感谢示例)

我刚刚取消了两个包含我的存储库、工作单元和数百个文件的接口的项目,因为没有看到回报。我想很多人,包括我自己,都加入了存储库的行列,因为其他人都在这么做,但回想起来,我认为这真的是一次无路可走的旅程

/叹息


理查德

你想把它们放在哪里?您只有很少的选择:

  • 让它们保持原样,并使用自定义扩展方法、映射的数据库视图或自定义来定义可重用零件
  • 将每个查询作为方法公开在某个单独的类上。方法不能公开
    IQueryable
    ,也不能接受
    表达式
    作为参数=整个查询逻辑必须包装在方法中。但这将使您的类覆盖的相关方法非常类似于存储库(唯一可以模拟或伪造的方法)。此实现与存储过程使用的实现非常接近
  • 您将执行与前面方法相同的操作,但不是将查询放在单独的类中,而是将它们作为静态方法直接放在实体中。这是更糟糕的可测试性,因为静态方法不能被模拟取代(它需要更复杂的测试框架)。这是每个实体负责加载和保存到数据库的部分
  • 自定义扩展方法的示例:

    public static IQueryable<TEntity> GetByName(this IQueryalbe<TEntity> query, string name) 
        where TEntity : IEntityWithName
    {
        return query.Where(e => e.Name == name);
    }
    
    公共静态IQueryable GetByName(此IQueryalbe查询,字符串名称)
    其中tenty:ientitywhithname
    {
    返回query.Where(e=>e.Name==Name);
    }
    
    自定义类公开方法的示例:

    public class QueryProvider
    {
        public QueryProvider() {}
    
        public IEnumerable<TEntity> GetByName(IYourContext context, string name)
            where TEntity : IEntityWithName
        {
            return context.CreateObjectSet<TEntity>().Where(e => e.Name == name).ToList();
        }
    }
    
    公共类查询提供程序
    {
    公共查询提供程序(){}
    public IEnumerable GetByName(IYourContext上下文,字符串名称)
    其中tenty:ientitywhithname
    {
    返回context.CreateObjectSet().Where(e=>e.Name==Name.ToList();
    }
    }
    

    这是我写的一篇关于构建可重用查询的博客文章。使用扩展方法可以构建可组合查询

    使用类似于规范模式的模式可以帮助您构建可重用或保存(序列化)的查询。此外,如果您有复式输入系统,则可以在两个不同的数据库上执行相同的查询实例

    下面的示例不使用EF,而是将IEnumerable替换为EF上下文,这样您就得到了所需的内容。参数通过构造函数传入

    public class PartialMatchQuery : IModelQuery<string, IEnumerable<string>>
    {
        private readonly string partial;
    
        public PartialMatchQuery(string partialString)
        {
            partial = partialString;
        }
    
        public IEnumerable<string> Execute(IEnumerable<string> model)
        {
            return model.Where(s => s.ToLower().Contains(partial));
        }
    }
    
    公共类PartialMatchQuery:IModelQuery
    {
    私有只读字符串部分;
    公共PartialMatchQuery(字符串partialString)
    {
    部分=部分字符串;
    }
    公共IEnumerable执行(IEnumerable模型)
    {
    返回模型,其中(s=>s.ToLower().Contains(partial));
    }
    }
    
    Entity Framework&Testing在我看来近乎矛盾,但我知道你的意思。一旦事情变得复杂,上述方法就会分崩离析,但正如你所说,还有什么?将其全部封装在存储库中只是将责任转移到其他地方。