DB First 中對Repository 層封裝的幾點小記

在數據庫表建立完成的狀況下,使用DB First 進行開發,封裝底層會遇到一些小問題,在此記錄一下,供之後參考。sql

主要解決的問題有:數據庫

一、EF上下文管理json

二、BaseRepository的封裝ide

三、EF中實體序列化的問題oop

 

一、EF上下文管理this

          EF操做數據庫的上下文,要達到在用戶每一次的請求操做中都只有一個上下文,當用戶經過Http請求結束後要釋放用戶使用的上下文資源,也就spa

是EF生成中的ObjectContext不能每次使用時候經過new 建立一個新的實例,一次請求只須要建立一次,請求結束ObjectContext資源釋放。調試

          這裏要用到的就是單例模式和簡單工廠了,單例保證只有一個ObjectContext ,每次調用經過工廠方式獲取。這裏直接貼代碼code

 

 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中,在請求結束事件中調用釋放資源方法。orm

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


     Debug.WriteLine是調試時候,追蹤一下上下文的獲取和釋放是否達到目的。打開調試的Output ,檢測到一次請求的輸出信息

          

    能夠看到,在此次請求處理中使用了兩次上下文實例,都是同一個實例(HashCode相同),最後又一次的資源釋放。

二、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也就實現了事務統一。

三、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
相關文章
相關標籤/搜索