EF對資料庫CRUD的泛型方法
阿新 • • 發佈:2021-06-26
這兩天在做期末作業,對兩張表進行增刪改查等操作,寫一堆重複程式碼。。。。
然後寫了一些泛型方法,來應對不同
using System; using System.Collections.Generic; using System.Data.Entity; using System.Data.Entity.Infrastructure; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Text; using System.Threading.Tasks; namespaceDAL { /// <summary> /// MSSql 資料庫 資料層 父類 /// </summary> /// <typeparam name="T"></typeparam> public class BaseDAL<T> where T : class, new() { /// <summary> /// EF 上下文物件 /// </summary> DbContext db = new DBContextFactory().GetDbContext();#region 1.0 新增實體,返回受影響的行數 + int Add(T model) /// <summary> /// 1.0 新增實體,返回受影響的行數 /// </summary> /// <param name="model"></param> /// <returns>返回受影響的行數</returns> public int Add(T model) { db.Set<T>().Add(model);//儲存成功後,會將自增的id設定給model的主鍵屬性,並返回受影響的行數。 return db.SaveChanges(); } #endregion #region 1.1 新增實體,返回對應的實體物件 + T AddReturnModel(T model) /// <summary> /// 1.1 新增實體,返回對應的實體物件 /// </summary> /// <param name="model"></param> /// <returns></returns> public T AddReturnModel(T model) { db.Set<T>().Add(model); db.SaveChanges(); return model; } #endregion #region 2.0 根據id刪除 + int Del(T model) /// <summary> /// 2.0 根據id刪除 /// </summary> /// <param name="model">必須包含要刪除id的物件</param> /// <returns></returns> public int Del(T model) { db.Set<T>().Attach(model); db.Set<T>().Remove(model); return db.SaveChanges(); } #endregion #region 2.1 根據條件刪除 + int DelBy(Expression<Func<T, bool>> delWhere) /// <summary> /// 2.1 根據條件刪除 /// </summary> /// <param name="delWhere"></param> /// <returns>返回受影響的行數</returns> public int DelBy(Expression<Func<T, bool>> delWhere) { //2.1.1 查詢要刪除的資料 List<T> listDeleting = db.Set<T>().Where(delWhere).ToList(); //2.1.2 將要刪除的資料 用刪除方法新增到 EF 容器中 listDeleting.ForEach(u => { db.Set<T>().Attach(u); //先附加到EF 容器 db.Set<T>().Remove(u); //標識為刪除狀態 }); //2.1.3 一次性生成sql語句 到資料庫執行刪除 return db.SaveChanges(); } #endregion #region 3.0 修改實體 + int Modify(T model) /// <summary> /// 修改實體 /// </summary> /// <param name="model"></param> /// <returns></returns> public int Modify(T model) { DbEntityEntry entry = db.Entry<T>(model); entry.State = System.Data.Entity.EntityState.Modified; return db.SaveChanges(); } #endregion #region 3.1 修改實體,可修改指定屬性 + int Modify(T model, params string[] propertyNames) /// <summary> /// 3.1 修改實體,可修改指定屬性 /// </summary> /// <param name="model"></param> /// <param name="propertyName"></param> /// <returns></returns> public int Modify(T model, params string[] propertyNames) { //3.1.1 將物件新增到EF中 DbEntityEntry entry = db.Entry<T>(model); //3.1.2 先設定物件的包裝狀態為 Unchanged entry.State = System.Data.Entity.EntityState.Unchanged; //3.1.3 迴圈被修改的屬性名陣列 foreach (string propertyName in propertyNames) { //將每個被修改的屬性的狀態設定為已修改狀態;這樣在後面生成的修改語句時,就只為標識為已修改的屬性更新 entry.Property(propertyName).IsModified = true; } return db.SaveChanges(); } #endregion #region 3.2 批量修改 + int ModifyBy(T model, Expression<Func<T, bool>> whereLambda, params string[] modifiedPropertyNames) /// <summary> /// 3.2 批量修改 /// </summary> /// <param name="model"></param> /// <param name="whereLambda"></param> /// <param name="modifiedPropertyNames"></param> /// <returns></returns> public int ModifyBy(T model, Expression<Func<T, bool>> whereLambda, params string[] modifiedPropertyNames) { //3.2.1 查詢要修改的資料 List<T> listModifing = db.Set<T>().Where(whereLambda).ToList(); //3.2.2 獲取實體類型別物件 Type t = typeof(T); //3.2.3 獲取實體類所有的公共屬性 List<PropertyInfo> propertyInfos = t.GetProperties(BindingFlags.Instance | BindingFlags.Public).ToList(); //3.2.4 建立實體屬性字典集合 Dictionary<string, PropertyInfo> dicPropertys = new Dictionary<string, PropertyInfo>(); //3.2.5 將實體屬性中要修改的屬性名 新增到字典集合中 鍵:屬性名 值:屬性物件 propertyInfos.ForEach(p => { if (modifiedPropertyNames.Contains(p.Name)) { dicPropertys.Add(p.Name, p); } }); //3.2.6 迴圈要修改的屬性名 foreach (string propertyName in modifiedPropertyNames) { //判斷要修改的屬性名是否在實體類的屬性集合中存在 if (dicPropertys.ContainsKey(propertyName)) { //如果存在,則取出要修改的屬性物件 PropertyInfo proInfo = dicPropertys[propertyName]; //取出要修改的值 object newValue = proInfo.GetValue(model, null); //批量設定要修改物件的屬性 foreach (T item in listModifing) { //為要修改的物件的要修改的屬性設定新的值 proInfo.SetValue(item, newValue, null); } } } //一次性生成sql語句 到資料庫執行 return db.SaveChanges(); } #endregion //改 #region 4.0 根據條件查詢單個model + T GetModel(Expression<Func<T, bool>> whereLambda) /// <summary> /// 4.0 根據條件查詢單個model /// </summary> /// <param name="whereLambda"></param> /// <returns></returns> public T GetModel(Expression<Func<T, bool>> whereLambda) { return db.Set<T>().Where(whereLambda).AsNoTracking().FirstOrDefault(); } #endregion #region 4.1 根據條件查詢單個model並排序 + T GetModel<TKey>(Expression<Func<T, bool>> whereLambda, Expression<Func<T, TKey>> orderLambda, bool isAsc = true) /// <summary> /// 4.1 根據條件查詢單個model並排序 /// </summary> /// <typeparam name="TKey"></typeparam> /// <param name="whereLambda"></param> /// <param name="orderLambda"></param> /// <param name="isAsc"></param> /// <returns></returns> public T GetModel<TKey>(Expression<Func<T, bool>> whereLambda, Expression<Func<T, TKey>> orderLambda, bool isAsc = true) { if (isAsc) { return db.Set<T>().Where(whereLambda).OrderBy(orderLambda).AsNoTracking().FirstOrDefault(); } else { return db.Set<T>().Where(whereLambda).OrderByDescending(orderLambda).AsNoTracking().FirstOrDefault(); } } #endregion //查單個model #region 5.0 根據條件查詢 + List<T> GetListBy(Expression<Func<T, bool>> whereLambda) /// <summary> /// 5.0 根據條件查詢 /// </summary> /// <param name="whereLambda"></param> /// <returns></returns> public List<T> GetListBy(Expression<Func<T, bool>> whereLambda) { return db.Set<T>().Where(whereLambda).AsNoTracking().ToList(); } #endregion #region 5.1 根據條件查詢,並排序 + List<T> GetListBy<TKey>(Expression<Func<T, bool>> whereLambda, Expression<Func<T, TKey>> orderLambda, bool isAsc = true) /// <summary> /// 5.1 根據條件查詢,並排序 /// </summary> /// <typeparam name="TKey"></typeparam> /// <param name="whereLambda"></param> /// <param name="orderLambda"></param> /// <param name="isAsc"></param> /// <returns></returns> public List<T> GetListBy<TKey>(Expression<Func<T, bool>> whereLambda, Expression<Func<T, TKey>> orderLambda, bool isAsc = true) { if (isAsc) { return db.Set<T>().Where(whereLambda).OrderBy(orderLambda).AsNoTracking().ToList(); } else { return db.Set<T>().Where(whereLambda).OrderByDescending(orderLambda).AsNoTracking().ToList(); } } #endregion #region 5.2 根據條件查詢Top多少個,並排序 + List<T> GetListBy<TKey>(int top, Expression<Func<T, bool>> whereLambda, Expression<Func<T, TKey>> orderLambda, bool isAsc = true) /// <summary> /// 5.2 根據條件查詢Top多少個,並排序 /// </summary> /// <typeparam name="TKey"></typeparam> /// <param name="top"></param> /// <param name="whereLambda"></param> /// <param name="orderLambda"></param> /// <param name="isAsc"></param> /// <returns></returns> public List<T> GetListBy<TKey>(int top, Expression<Func<T, bool>> whereLambda, Expression<Func<T, TKey>> orderLambda, bool isAsc = true) { if (isAsc) { return db.Set<T>().Where(whereLambda).OrderBy(orderLambda).Take(top).AsNoTracking().ToList(); } else { return db.Set<T>().Where(whereLambda).OrderByDescending(orderLambda).Take(top).AsNoTracking().ToList(); } } #endregion #region 5.3 根據條件排序查詢 雙排序 + List<T> GetListBy<TKey1, TKey2>(Expression<Func<T, bool>> whereLambda, Expression<Func<T, TKey1>> orderLambda1, Expression<Func<T, TKey2>> orderLambda2, bool isAsc1 = true, bool isAsc2 = true) /// <summary> /// 5.3 根據條件排序查詢 雙排序 /// </summary> /// <typeparam name="TKey1"></typeparam> /// <typeparam name="TKey2"></typeparam> /// <param name="whereLambda"></param> /// <param name="orderLambda1"></param> /// <param name="orderLambda2"></param> /// <param name="isAsc1"></param> /// <param name="isAsc2"></param> /// <returns></returns> public List<T> GetListBy<TKey1, TKey2>(Expression<Func<T, bool>> whereLambda, Expression<Func<T, TKey1>> orderLambda1, Expression<Func<T, TKey2>> orderLambda2, bool isAsc1 = true, bool isAsc2 = true) { if (isAsc1) { if (isAsc2) { return db.Set<T>().Where(whereLambda).OrderBy(orderLambda1).ThenBy(orderLambda2).AsNoTracking().ToList(); } else { return db.Set<T>().Where(whereLambda).OrderBy(orderLambda1).ThenByDescending(orderLambda2).AsNoTracking().ToList(); } } else { if (isAsc2) { return db.Set<T>().Where(whereLambda).OrderByDescending(orderLambda1).ThenBy(orderLambda2).AsNoTracking().ToList(); } else { return db.Set<T>().Where(whereLambda).OrderByDescending(orderLambda1).ThenByDescending(orderLambda2).AsNoTracking().ToList(); } } } #endregion #region 5.3 根據條件排序查詢Top個數 雙排序 + List<T> GetListBy<TKey1, TKey2>(int top, Expression<Func<T, bool>> whereLambda, System.Linq.Expressions.Expression<Func<T, TKey1>> orderLambda1, Expression<Func<T, TKey2>> orderLambda2, bool isAsc1 = true, bool isAsc2 = true) /// <summary> /// 5.3 根據條件排序查詢Top個數 雙排序 /// </summary> /// <typeparam name="TKey1"></typeparam> /// <typeparam name="TKey2"></typeparam> /// <param name="top"></param> /// <param name="whereLambda"></param> /// <param name="orderLambda1"></param> /// <param name="orderLambda2"></param> /// <param name="isAsc1"></param> /// <param name="isAsc2"></param> /// <returns></returns> public List<T> GetListBy<TKey1, TKey2>(int top, Expression<Func<T, bool>> whereLambda, Expression<Func<T, TKey1>> orderLambda1, Expression<Func<T, TKey2>> orderLambda2, bool isAsc1 = true, bool isAsc2 = true) { if (isAsc1) { if (isAsc2) { return db.Set<T>().Where(whereLambda).OrderBy(orderLambda1).ThenBy(orderLambda2).Take(top).AsNoTracking().ToList(); } else { return db.Set<T>().Where(whereLambda).OrderBy(orderLambda1).ThenByDescending(orderLambda2).Take(top).AsNoTracking().ToList(); } } else { if (isAsc2) { return db.Set<T>().Where(whereLambda).OrderByDescending(orderLambda1).ThenBy(orderLambda2).Take(top).AsNoTracking().ToList(); } else { return db.Set<T>().Where(whereLambda).OrderByDescending(orderLambda1).ThenByDescending(orderLambda2).Take(top).AsNoTracking().ToList(); } } } #endregion //查List #region 6.0 分頁查詢 + List<T> GetPagedList<TKey> /// <summary> /// 分頁查詢 + List<T> GetPagedList /// </summary> /// <typeparam name="TKey"></typeparam> /// <param name="pageIndex">頁碼</param> /// <param name="pageSize">頁容量</param> /// <param name="whereLambda">條件 lambda表示式</param> /// <param name="orderBy">排序 lambda表示式</param> /// <returns></returns> public List<T> GetPagedList<TKey>(int pageIndex, int pageSize, Expression<Func<T, bool>> whereLambda, Expression<Func<T, TKey>> orderByLambda, bool isAsc = true) { // 分頁 一定注意: Skip 之前一定要 OrderBy if (isAsc) { return db.Set<T>().Where(whereLambda).OrderBy(orderByLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize).AsNoTracking().ToList(); } else { return db.Set<T>().Where(whereLambda).OrderByDescending(orderByLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize).AsNoTracking().ToList(); } } #endregion #region 6.1分頁查詢 帶輸出 +List<T> GetPagedList<TKey> /// <summary> /// 分頁查詢 帶輸出 /// </summary> /// <typeparam name="TKey"></typeparam> /// <param name="pageIndex"></param> /// <param name="pageSize"></param> /// <param name="rowCount"></param> /// <param name="whereLambda"></param> /// <param name="orderBy"></param> /// <param name="isAsc"></param> /// <returns></returns> public List<T> GetPagedList<TKey>(int pageIndex, int pageSize, ref int rowCount, Expression<Func<T, bool>> whereLambda, Expression<Func<T, TKey>> orderByLambda, bool isAsc = true) { rowCount = db.Set<T>().Where(whereLambda).Count(); if (isAsc) { return db.Set<T>().OrderBy(orderByLambda).Where(whereLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize).AsNoTracking().ToList(); } else { return db.Set<T>().OrderByDescending(orderByLambda).Where(whereLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize).AsNoTracking().ToList(); } } #endregion #region 6.2 分頁查詢 帶輸出 並支援雙欄位排序 /// <summary> /// 分頁查詢 帶輸出 並支援雙欄位排序 /// </summary> /// <typeparam name="TKey"></typeparam> /// <param name="pageIndex"></param> /// <param name="pageSize"></param> /// <param name="rowCount"></param> /// <param name="whereLambda"></param> /// <param name="orderByLambda1"></param> /// <param name="orderByLambda2"></param> /// <param name="isAsc1"></param> /// <param name="isAsc2"></param> /// <returns></returns> public List<T> GetPagedList<TKey1, TKey2>(int pageIndex, int pageSize, ref int rowCount, Expression<Func<T, bool>> whereLambda, Expression<Func<T, TKey1>> orderByLambda1, Expression<Func<T, TKey2>> orderByLambda2, bool isAsc1 = true, bool isAsc2 = true) { rowCount = db.Set<T>().Where(whereLambda).Count(); if (isAsc1) { if (isAsc2) { return db.Set<T>().OrderBy(orderByLambda1).ThenBy(orderByLambda2).Where(whereLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize).AsNoTracking().ToList(); } else { return db.Set<T>().OrderBy(orderByLambda1).ThenByDescending(orderByLambda2).Where(whereLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize).AsNoTracking().ToList(); } } else { if (isAsc2) { return db.Set<T>().OrderByDescending(orderByLambda1).ThenBy(orderByLambda2).Where(whereLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize).AsNoTracking().ToList(); } else { return db.Set<T>().OrderByDescending(orderByLambda1).ThenByDescending(orderByLambda2).Where(whereLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize).AsNoTracking().ToList(); } } } #endregion } }
注意,ef上下文物件要保持唯一性,,,,自己在做的時候一個方法用了兩次,一直報錯。。。。找了好多方法,其實方法很簡單保持唯一就好
錯誤截圖: