首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >存储库实现

存储库实现
EN

Stack Overflow用户
提问于 2013-02-27 16:35:15
回答 1查看 145关注 0票数 3

我正在考虑改进我当前的存储库GetAll方法实现,并编写了下面的代码。我试图在谷歌中找到这种方法的想法,但没有成功。因此,请检查代码,并帮助我回答下面的一些问题。以下是简化的示例:

代码语言:javascript
复制
class Service
{
    public void DoOperation()
    {
        // Let's say we need to retrieve users by criteria
        var items = UnitOfWork
            .Over<User>() // Get repository of User
            .GetAll()     // Start querying

            // If we need simple WHERE then use:
            .Where(x => x.Email == "some@email.com")

            // If we need more complex condition then use specification:
            .Using(new UserNameContains("John"))

            // Execute:
            .List();
    }
}

class UnitOfWork
{
    public Repository<T> Over<T>()
    {
        // Get from DI container or injected field
        return new Repository<T>();
    }
}

class Repository<T>
{
    public QueryWrapper<T> GetAll()
    {
        return new QueryWrapper<T>(Session.QueryOver<T>());
    }
}

class QueryWrapper<T>
{
    // Query from DB session. Init from constructor.
    private IQueryOver<T> _query;

    public QueryWrapper<T> Where(Expression<Func<T, bool>> expression)
    {
        _query = _query.Where(expression);
        return this;
    }

    public QueryWrapper<T> Using(Specification<T> spec)
    {
        var spec = new TSpec();
        _query = spec.Apply(_query);
        return this;
    }

    public IEnumerable<T> List()
    {
        return return _query.List();
    }
}

abstract class Specification<T>
{
    public abstract IQueryOver<T> Apply(IQueryOver<T> query);
}

class UserNameContains : Specification<User>
{
    // Init from constructor:
    private string _name;

    public override IQueryOver<User> Apply(IQueryOver<User> query)
    {
        return /* apply filter condition here */;
    }
}

因此,我们得到了这样的好处:

  1. 不再需要创建自定义Repos。单一的通用就足够了。
  2. 自定义规范实现现在与数据层分离,并且可测试。
  3. 易于使用的服务。
  4. 我们总是能够扩展QueryWrapper以支持其他方法,如OrderBy等。
  5. 它仍然是可测试的单元。

请你指出我的方法的漏洞,或者提供你对这个问题的看法?此外,链接到现有的文章将是很好的。

EN

回答 1

Stack Overflow用户

发布于 2013-03-01 14:43:18

我的建议是将体系结构降到最低限度,并为自己证明每个添加的层和抽象的好处。最小的GetAll实现是:

代码语言:javascript
复制
Session.Query<User>();

如果您有将被重用的限制,则可以将它们添加为扩展方法。如果您的可重用代码变得显而易见,那么重构到扩展方法就足够简单了。即使这样,对于简单的情况,如果您只是包装Lambda表达式,那么重构通常也没有什么好处,如本例所示。

代码语言:javascript
复制
public static IQueryable<User> UserNameContains(this IQueryable<User> queryable, string text)
{
    return queryable.Where(u => u.UserNameContains(text));
}

我不认为存储库模式非常有用,但它可以是组织代码的合理方法。但是我真的不喜欢通用存储库模式,因为它强制每个类规则一个存储库。如果我使用存储库,我喜欢对与根对象相关的查询进行分组(如Project、ProjectStatus等)。此外,在通用存储库中提供Get或GetAll方法没有好处,因为ISession已经提供了这些方法。

至于可测试性,查询的测试总是集成测试,在ASP.NET MVC中,我直接测试控制器或任何独立的查询方法。我在Windows窗体项目中使用存储库进行测试。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15117327

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档