我使用的IRepository是否正确? [英] Am I using IRepository correctly?

查看:206
本文介绍了我使用的IRepository是否正确?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我期待在一个小项目中使用的IRepository模式(由NHibernate的支持,如果它事项)。该域名是一个简单的,所以故意让我着重了解IRepository模式。孤独的领域类是电影新年性能类型标题。我的目的是获取的电影,其性质符合上述类型的标准。

I'm looking to use the IRepository pattern (backed by NHibernate, if it matters) in a small project. The domain is a simple one, intentionally so to allow me to focus on understanding the IRepository pattern. The lone domain class is Movie, with properties for Year, Genre, and Title. My intent would be to "get" movies whose properties match criteria of the aforementioned types.

公约似乎有一个通用的 IRepository 界面,类似以下内容:

Convention seems to be to have a generic IRepository interface, similar to the following:

public interface IRepository<T>
{
    T Get(int id);
    T[] GetAll();
    void Add(T item);
    void Update(T item);
    void Delete(T item);
}

通过基地实现:

public abstract class Repository<T> : IRepository<T>
{
    public T Get(int id) { ... }
    public T[] GetAll() { ... }
    public void Add(T item) { ... }
    public void Update(T item) { ... }
    public void Delete(T item) { ... }
}

然后有一个特定领域的接口:

Then to have a domain-specific interface:

public interface IMovieRepository
{
    Movie[] GetByGenre(Genre genre);
    Movie[] GetByYear(int year);
    Movie[] GetByTitle(string title);
}

使用也扩展基础库<实施/ code>类:

With an implementation that also extends the base Repository class:

public class MovieRepository : Repository<Movie>, IMovieRepository
{
    public Movie[] GetByGenre(Genre genre) { ... }
    public Movie[] GetByYear(int year) { ... }
    public Movie[] GetByTitle(string title) { ... }
}

我需要必要的实施增加了基类还有具体的,使用NHibernate的,但我想知道如果我在正确的轨道与此设置上。

I would need to add necessary implementation to the base class as well as the concrete one, using NHibernate, but I would like to know if I am on the right track with this setup.

有似乎开销公平一点只是一个域类,虽然它会如果有涉及到多个领域类不太明显。现在,我试图保持它的简单,所以我可以牵制的概念。

There seems to be a fair bit of overhead for just one domain class, though it would be less noticeable if there were multiple domain classes involved. Right now I'm trying to keep it simple so I can pin down the concept.

推荐答案

我说,你是接近我对运输公司(使用NHibernate以及)资源规划的生产解决方案使用存储库 - 所以对于初学者你是在我看来,在正确的道路上。我dbones同意使用IEnumerables / IList的,而不是阵列 - 你最终会在写.ToArray()多次: - )

I'd say, you are close to the repository that I use in a production solution for resource planning in Transport companies (using NHibernate as well) - so for starters you are on the right path in my opinion. I agree with dbones on using IEnumerables /IList instead of arrays - you'll end up writing .ToArray() many times over :-).

有几件事情你可能考虑:

A few things you might consider:

恩构成了传承 - 而不是从抽象库继承 - 让它成为非抽象并在构造函数注入,并委托电话 - 这使得你的设计在某些情况下更稳健(如查询,只有库等),这样,你也可以让抽象库是可实例化的选项(就是一个字?),并控制是否应在所有库共享。

Favour Composition over inheritance - instead of inheriting from the abstract repository - let it be non-abstract and inject it in the 'ctor and delegate the calls - this makes your design more robust in certain situations (e.g. for a Query-only repository etc.) That way you also have the option of letting the abstract repository be instantiatable (is that a word?) and control whether it should be shared across all repositories.

在这一点上跟进 - 您可能要更改基本信息库有通用的方法,而不是从通用接口继承:

Following up on that point - you might want to change the base Repository to have generic methods instead of inheriting from the generic interface:

public class Repository
{
    public void Add<T>(T entity)
    {
        using(var session = GetSession())
        using(var tx = session.BeginTransaction())
        {
             session.Save(entity)
             //Transaction handling etc.
        }
    }
    .... //repeat ad nasseum :-)
}

您可能希望让特定的仓库有机会获得的ISession - 这大大提高了你可以如何灵活让你的查询和控制急于/延迟抓取,你会得到充分利用的NHibernate等例的

You might want to let the specific repositories have access to the ISession - this greatly improves how flexible you can make your queries and control eager/lazy fetching and you get full advantage of NHibernate etc. E.g.

public class Repository
{
    public IList<T> WrapQueryInSession<T>(Func<ISession,IList<T> query)
    {
        using(var session = GetSession())
        using(var tx = session.BeginTransaction())
        {
             var items = query(session);
             //Handle exceptions transacitons etc.
             return items;
        }
     }
 }



用法:

Usage:

public class MovieRepository : IMovieRepository
{
    private Repository _repository;
    public MovieRepository(Repository repository)
    {
        _repository = repository;
    }
    public IList<Movie> GetByYear(int year)
    {
        Func<ISession, IList<Movie> query = session =>
        {
            var query = session.CreateQuery("from Movie"); //or
            var query = session.CreateCriteria("from Movie"); //or
            var query = session.Linq<Movie>();
            //set criteria etc.
            return query.List<Movie>(); //ToList<Movie>() if you're using Linq2NHibernate
        }:
        return _repository.WrapQueryInSession(query);
    }
}

您可能还需要上设置一个布尔返回值你的方法,如果出现错误 - 也许一出IEnumerable的任何错误,这将使调用代码意义

You might also want to set a bool return value on your methods if something goes wrong - and maybe an out IEnumerable for any errors that will make sense in the calling code.

但所有的一切 - 这些只是我的花絮是我已经随着时间的推移添加符合我的使用更好 - 他们是完全可选的,只是回味无穷:-)。我认为你是在正确的道路上 - 我没有看到你的代码中的任何重大问题。

But all in all - these are just my tidbits that I have added over time to comply better with my usage - and they are entirely optional, just food for thought :-). I think you are on the right path - I don't see any major problems in your code.

希望这是有道理的: - )

Hope this makes sense :-)

这篇关于我使用的IRepository是否正确?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆