基于EF4.1的异构数据库访问组件(三)
接上一篇
基于EF4.1的异构数据库访问组件(二)中已完成了该组件的核心部分:
- IDbContextStorage – DbContext仓库
- IDbContextBuilder - DbContext动态组建器
- IDbContextManager – DbContext管理器
接下来,向大家介绍一下第一篇所说的,给上层提供统一的持久数据接口。
IRepository<T>
IRepository<T>就是需要提供给上层的统一数据持久接口,这里大家可以找到很多的例子,不多说,直接上类图:
上图中有以下几个主要部分:
- IRepository<T> - 数据持久接口
- SortOrder枚举 - 排序方式枚举
- IUnitOfWork - 工作单元接口
- UnitOfWork - 工作单元实现类
- EFRepository<T> - 数据持久实现基类
关于IUnitOfWork与IRepository<T>这块大家可以在园子里面找找文章,这里需要说明的是——我们怎样去确定哪个业务对象属于哪个数据库呢,关键在于EFRepository<T>这个基类的构造函数中:
public EFRepository(string connectionStringName) { _connectionStringName = connectionStringName; } private DbContext DbContext { get { if (_context == null) { if (string.IsNullOrEmpty(_connectionStringName)) throw new Exception("实例化数据持久化类时,未对_connectionStringName进行赋值μ"); _context = DbContextManager.CurrentByKey(_connectionStringName); } return _context; } }
PagedList<T>分页
在IRepository<T>中,我们提供了获取数据分页的方法。我采用的方法是使用PagedList<T>容器及扩展方法来实现的,EFRepository<T>的实现代码:
/// <summary> /// 根据条件及排序字段获取分页列表 /// </summary> public PagedList<T> GetPagedList(Expression<Func<T, bool>> predicate, string orderBy, SortOrder sortOrder, int pageIndex, int pageSize) { return DbContext.Set<T>().Where(predicate) .OrderBy(orderBy, sortOrder) .ToPagedList(pageIndex, pageSize); }下面来看看PagedList<T>及扩展方法ToPagedList
public class PagedList<T> : List<T> { public PagedList(IList<T> items,int pageIndex,int pageSize) { PageSize = pageSize; TotalItemCount = items.Count; TotalPageCount = (int)Math.Ceiling(TotalItemCount / (double)PageSize); CurrentPageIndex = pageIndex; StartRecordIndex=(CurrentPageIndex - 1) * PageSize + 1; EndRecordIndex = TotalItemCount > pageIndex * pageSize ? pageIndex * pageSize : TotalItemCount; for (int i = StartRecordIndex-1; i < EndRecordIndex;i++ ) { Add(items[i]); } } public PagedList(IEnumerable<T> items, int pageIndex, int pageSize, int totalItemCount) { AddRange(items); TotalItemCount = totalItemCount; TotalPageCount = (int)Math.Ceiling(totalItemCount / (double)pageSize); CurrentPageIndex = pageIndex; PageSize = pageSize; StartRecordIndex = (pageIndex - 1) * pageSize + 1; EndRecordIndex = TotalItemCount > pageIndex * pageSize ? pageIndex * pageSize : totalItemCount; } public int CurrentPageIndex { get; set; } public int PageSize { get; set; } public int TotalItemCount { get; set; } public int TotalPageCount{get; private set;} public int StartRecordIndex{get; private set;} public int EndRecordIndex{get; private set;} }public static class PageLinqExtensions { public static PagedList<T> ToPagedList<T> ( this IQueryable<T> allItems, int pageIndex, int pageSize ) { if (pageIndex < 1) pageIndex = 1; var itemIndex = (pageIndex - 1) * pageSize; var pageOfItems = allItems.Skip(itemIndex).Take(pageSize); var totalItemCount = allItems.Count(); return new PagedList<T>(pageOfItems, pageIndex, pageSize, totalItemCount); } public static PagedList<T> ToPagedList<T> ( this IEnumerable<T> allItems, int pageIndex, int pageSize ) { if (pageIndex < 1) pageIndex = 1; var itemIndex = (pageIndex - 1) * pageSize; var pageOfItems = allItems.Skip(itemIndex).Take(pageSize); var totalItemCount = allItems.Count(); return new PagedList<T>(pageOfItems, pageIndex, pageSize, totalItemCount); } public static PagedList<T> ToPagedList<T> ( this IQueryable<T> allItems, int pageIndex, int pageSize, int totalCount ) { if (pageIndex < 1) pageIndex = 1; var totalItemCount = totalCount; return new PagedList<T>(allItems, pageIndex, pageSize, totalItemCount); } public static PagedList<T> ToPagedList<T> ( this IEnumerable<T> allItems, int pageIndex, int pageSize, int totalCount ) { if (pageIndex < 1) pageIndex = 1; var totalItemCount = totalCount; return new PagedList<T>(allItems, pageIndex, pageSize, totalItemCount); } }
关于排序
直接新增扩展方法OrderBy
public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, string propertyName, SortOrder sortOrder) where T : class { var type = typeof(T); var property = type.GetProperty(propertyName); if (property == null) throw new ArgumentException("propertyName", "不?存?在ú"); var param = Expression.Parameter(type, "p"); Expression propertyAccessExpression = Expression.MakeMemberAccess(param, property); var orderByExpression = Expression.Lambda(propertyAccessExpression, param); var methodName = sortOrder == SortOrder.Ascending ? "OrderBy" : "OrderByDescending"; var resultExp = Expression.Call(typeof(Queryable), methodName, new Type[] { type, property.PropertyType }, source.Expression, Expression.Quote(orderByExpression)); return source.Provider.CreateQuery<T>(resultExp); }
多条件动态查询
参考:http://blogs.msdn.com/b/meek/archive/2008/05/02/linq-to-entities-combining-predicates.aspx
呵呵,差不多这个组件就是这样子了,我会把代码作一个整理放到Codeplex上面,到时有需要的朋友请关注,谢谢!