统一的仓储接口

目前,各种数据访问组件多如牦牛,提供接口各不相同,虽然大多都支持不同数据存储,但是还是存在一些问题,

 有的团队成员喜欢用EF,有的喜欢用NHibernate,口味难调。于是我希望能有一组标准的接口,这样可以统一

代码的,也可以满足各成员的喜好。

目前来说,linq的出现,大大简化了代码的冗余和复杂性,

所以这组接口是建立在linq的基础上的,支持linq的数据访问组件目前有EF,NHibernate,IQtoolkit,Dblinq等。

 这里面有两个重要的对象,Context(上下文对象)和Repository(仓储对象)。

我希望调用者只需要尽量少的对象和尽量少的方法。使得接口清晰简单。

首先上下文对象Context,它能够获得仓储对象并完成事务提交即可。

public interface IObjectContext:IDisposable
{
     string Name { getset; }
    IRepository GetRepository<T>();

bool SaveChanges();

}

 接着仓储对象Repository,它则可以对T类型的数据进行CRUD,并且还能像IQueryable那样支持很多操作。

 public interface IRepository<T> : IQueryable<T> where T : class,IEntity, new()

    {
        T CreateModel();
        bool New(T entity);
        bool Update(T entity);
        bool Delete(T t);
        bool VirtualDelete(T t);
        Guid NewGuid();
        decimal NewId();
    }

仓储对不同数据访问组件有些共同的东西,加之实现IQueryable,所以增加抽象类AbstractRepository

public abstract class AbstractRepository<T> : IRepository<T> where T : class,IEntity, new()
    {
        public IObjectContext Context { getprivate set; }
        public AbstractRepository(IObjectContext context)
        {
            Context = context;
        }
        protected abstract IQueryable<T> GetQueryable();
        public abstract bool New(T entity);
        public abstract bool Update(T entity);
        public abstract bool Delete(T t);
        public abstract bool VirtualDelete(T t);
        public virtual T CreateModel()
        {
            return new T();
        }
        public virtual Guid NewGuid() { return Guid.NewGuid(); }
        public virtual decimal NewId() { return decimal.Zero; }

        public IEnumerator<T> GetEnumerator()
        {
            return GetQueryable().GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetQueryable().GetEnumerator();
        }

        public Type ElementType
        {
            get { return GetQueryable().ElementType; }
        }

        public Expression Expression
        {
            get { return GetQueryable().Expression; }
        }

        public IQueryProvider Provider
        {
            get { return GetQueryable().Provider; }
        }

    } 

主要的就需要这三个接口

 代码写起来就是这样子

 using (var context = ContextFactory.Create(contextName))

            {
                var r = context.GetRepository<T>();
                var instance = r.CreateModel();
                instance.Copy(tdto);
                instance.Validate(context);
                r.New(instance);
                context.SaveChanges();
                return instance;
            }

 这些重复性的代码,直接扩展到接口上,封装起来,外面只需继承此接口。

 下面是EF的仓储实现

 public class EFRepository<T> : AbstractRepository<T> where T : class,IEntity, new()

    {
        ObjectContext _context = null;
        public EFRepository(IObjectContext context) : base(context) {
            _context = base.Context as ObjectContext;
            if (_context == null) { throw new Exception("EFRepository中上下文对象不是System.Data.Objects.ObjectContext对象。"); }
        }
        public override bool New(T entity)
        {
            GetObjectSet().AddObject(entity);
            return true;
        }

        public override bool Update(T entity)
        {
            return true;
        }

        public override bool Delete(T t)
        {
            GetObjectSet().DeleteObject(t);
            return true;
        }

        public override bool VirtualDelete(T t)
        {
            return true;
        }

        protected override IQueryable<T> GetQueryable()
        {
            return GetObjectSet();
        }

        ObjectSet<T> GetObjectSet()
        {
            return _context.CreateObjectSet<T>();
        }
    }

其它的仓储实现也比较简单,附上源码

 Repository.rar

posted on 2011-11-09 14:25  bmrxntfj  阅读(1902)  评论(1编辑  收藏  举报