您的位置:首页 > 其它

统一的仓储接口

2011-11-09 14:25 113 查看
目前,各种数据访问组件多如牦牛,提供接口各不相同,虽然大多都支持不同数据存储,但是还是存在一些问题,

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

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

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

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

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

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

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

public interface IObjectContext:IDisposable

{

string Name { get; set; }

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 { get; private 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: