在數據庫表建立完成的狀況下,使用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 }
而後,在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 }
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 }