DB First 中对Repository 层封装的几点小记

在数据库表创建完成的情况下,使用DB First 进行开发,封装底层会遇到一些小问题,在此记录一下,供以后参考。

主要解决的问题有:

1、EF上下文管理

2、BaseRepository的封装

3、EF中实体序列化的问题

 

1、EF上下文管理

          EF操作数据库的上下文,要达到在用户每一次的请求操作中都只有一个上下文,当用户通过Http请求结束后要释放用户使用的上下文资源,也就

是EF生成中的ObjectContext不能每次使用时候通过new 创建一个新的实例,一次请求只需要创建一次,请求结束ObjectContext资源释放。

          这里要用到的就是单例模式和简单工厂了,单例保证只有一个ObjectContext ,每次调用通过工厂方式获取。这里直接贴代码

 

 1    public class DbContextFactory
 2     {
 3        private static string efKey = "ef_key";
 4 
 5        public static RBACEntities GetContext() 
 6        {
 7            RBACEntities db = CallContext.GetData(efKey) as RBACEntities;
 8            if (db == null) 
 9            {
10                db = new RBACEntities();
11                CallContext.SetData(efKey,db);
12            }
13            Debug.WriteLine("EF上下文获取:" + db.GetHashCode() + ",时间:" + DateTime.Now.ToString("hh-mm-ss ffff"));
14            return db;
15        }
16 
17        public static void Dispose() 
18        {
19            var context=GetContext();
20            Debug.WriteLine("EF上下文释放:" + context.GetHashCode() + ",时间:" + DateTime.Now.ToString("hh-mm-ss ffff"));
21            context.Dispose();
22        }
23     }
View Code

 然后,在Global.asax中,在请求结束事件中调用释放资源方法。

1        protected void Application_EndRequest()
2         {
3             Dedeyi.RBAC2.Core.Model.DbContextFactory.Dispose();
4         }


     Debug.WriteLine是调试时候,追踪一下上下文的获取和释放是否达到目的。打开调试的Output ,检测到一次请求的输出信息

          

    可以看到,在这次请求处理中使用了两次上下文实例,都是同一个实例(HashCode相同),最后又一次的资源释放。

2、BaseRepository的封装

        基仓储的封装。要实现基本的增删查改操作。在这里因为使用的是Entity Framework 中的ObjectContext进行数据库交互,其灵活性是很强的

如果只是像ADO.NET中通过sql对CRUD的封装那样,就很多地方没法发挥ObjectContex的作用了。

        所有我们在基类中要把这个上下文留出来,作为一个可以访问的属性。通过这个上下文,可以在自类中访问数据模型中其他表,ObjectSet 是对应当前EF实体对象,也把这个暴露给外面使用。然后就是分页和搜索的封装了。具体代码如下:

 

 1  public class BaseRepository<TEntity> where TEntity: EntityObject
 2     {
 3        protected RBACEntities RBACContext { get; set; }
 4        protected ObjectSet<TEntity> DbSet { get; set; }
 5 
 6        protected virtual IQueryable<TEntity> Entities 
 7        {
 8            get { return RBACContext.CreateObjectSet<TEntity>(); }
 9        }
10 
11        public BaseRepository() 
12        {
13            this.RBACContext = DbContextFactory.GetContext();
14            this.DbSet=RBACContext.CreateObjectSet<TEntity>();
15        }
16 
17        public IQueryable<TEntity> GetPage<TKey>(int pageIndex, int pageSize,Expression<Func<TEntity,TKey>> orderBy, out int totalRecord) 
18        {
19            totalRecord = DbSet.Count();
20            return  this.DbSet
21                       .OrderByDescending(orderBy)
22                       .Skip((pageIndex - 1) * pageSize)
23                       .Take(pageSize)
24                       .AsQueryable();
25        }
26 
27        public IQueryable<TEntity> GetPage<TKey>(int pageIndex, int pageSize, Expression<Func<TEntity, TKey>> orderBy, Expression<Func<TEntity, bool>> where, out int totalRecord)
28        {
29            var res=DbSet.Where(where);
30 
31            totalRecord = res.Count();
32            return  res
33                       .OrderByDescending(orderBy)
34                       .Skip((pageIndex - 1) * pageSize)
35                       .Take(pageSize)
36                       .AsQueryable();
37        }
38 
39 
40        public TEntity Add(TEntity entity,bool saveChange) 
41        {
42            RBACContext.CreateObjectSet<TEntity>().AddObject(entity);
43            if (saveChange) 
44            {
45                RBACContext.SaveChanges();
46            }
47            return entity;
48        }
49 
50        public TEntity Edit(TEntity entity, bool saveChange) 
51        {
52            RBACContext.CreateObjectSet<TEntity>().Attach(entity);
53            RBACContext.ObjectStateManager.ChangeObjectState(entity,System.Data.EntityState.Modified);
54            if (saveChange) 
55            {
56                RBACContext.SaveChanges();
57            }
58            return entity;
59        }
60 
61        public void Delete(TEntity entity, bool saveChange) 
62        {
63            RBACContext.CreateObjectSet<TEntity>().DeleteObject(entity);
64            if (saveChange) { RBACContext.SaveChanges(); }
65        }
66     }
View Code

 

      SaveChange是一个bool 类型参数,表明是否要上下文保存到数据库,如果只是修改一张表,直接保存,如果涉及多个操作,最后统一SaveChange也就实现了事务统一。

3、EF中实体序列化去除 EntityKey字段

      如果直接把EF模型数据表对应的模型进行序列化,会得到很多跟EF相关的属性,要去掉这些多余的属性,就响应对序列化进行一些修改了。

这里使用的是Newtonsoft.Net进行序列化的。具体封装源码:

 

 1     public class JsonNet
 2     {
 3         /// <summary>
 4         /// 将实体对象转换成Json字符串 
 5         /// </summary>
 6         /// <param name="item"></param>
 7         /// <returns></returns>
 8         public static string SerializeToString(object item)
 9         {
10            return JsonConvert.SerializeObject(item, Formatting.Indented,
11                 new JsonSerializerSettings
12                 {
13                     ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
14                     ContractResolver = new ExcludePropertiesContractResolver(new List<string> { "EntityKey" }),
15                 });
16 
17         }
18 
19         /// <summary>
20         /// 将Json字符串转换成实体对象
21         /// </summary>
22         /// <typeparam name="T"></typeparam>
23         /// <param name="jsonString"></param>
24         /// <returns></returns>
25         public static T DeserializeToEntity<T>(string jsonString)
26         {
27             return JsonConvert.DeserializeObject<T>(jsonString);
28         }
29     }
30 
31     public class ExcludePropertiesContractResolver : DefaultContractResolver
32     {
33         IEnumerable<string> lstExclude;
34 
35         public ExcludePropertiesContractResolver(IEnumerable<string> excludedProperties)
36         {
37             lstExclude = excludedProperties;
38         }
39 
40         protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
41         {
42             return base.CreateProperties(type, memberSerialization).ToList().FindAll(p => !lstExclude.Contains(p.PropertyName));
43         }
44     }
View Code

 

 

 

posted @ 2013-10-23 12:34  hello*boy  阅读(2277)  评论(2编辑  收藏  举报