在前面的博客就分別提到了要實現批量更新和刪除的函數,今天我也終於實現了.現在拿出來跟大家分享一下吧.
我們先來說批量刪除吧.請看代碼
public static int Delete<T>(this ObjectSet<T> ent, Expression<Func<T, bool>> where) where T : class { var query = ent.Where(where); ObjectQuery objQuery = query as ObjectQuery; string sql=objQuery.ToTraceString(); sql = "delete " + sql.Substring(sql.IndexOf("from", StringComparison.OrdinalIgnoreCase)); sql = sql.Replace("[Extent1].", "").Replace("AS [Extent1]", "").Replace("__linq__", ""); List<object> objs = new List<object>(); foreach (var para in objQuery.Parameters) { objs.Add(para.Value); } int index= ent.Context.ExecuteStoreCommand(sql, objs.ToArray()); return index; }
刪除其實也並不難,主要是通過查詢語句,作相應的修改就行了.
我們再看,修改語句.
public static int Update<T>(this ObjectSet<T> ent, Expression<Func<T, bool>> where, Expression<Func<T>> updater) where T : class { //where 語句 var query = ent.Where(where); ObjectQuery objQuery = query as ObjectQuery; List<object> objParams = new List<object>(); string sql = objQuery.ToTraceString(); sql = sql.Substring(sql.IndexOf("from", StringComparison.OrdinalIgnoreCase)).Replace("__linq__", ""); int paramindex = objQuery.Parameters.Count; foreach (var para in objQuery.Parameters) { objParams.Add(para.Value); } //獲取Update的賦值語句 var valueObj = updater.Compile().Invoke(); MemberInitExpression updateMemberExpr = (MemberInitExpression)updater.Body; StringBuilder updateBuilder = new StringBuilder(); Type valueType = typeof(T); foreach (var bind in updateMemberExpr.Bindings.Cast<MemberAssignment>()) { string name = bind.Member.Name; updateBuilder.AppendFormat("{0}=@p{1},", name, paramindex++); var value = valueType.GetProperty(name).GetValue(valueObj); objParams.Add(value); } if (updateBuilder.Length == 0) { throw new Exception("請填寫要更新的值"); } else { sql = " update [Extent1] set " + updateBuilder.Remove(updateBuilder.Length - 1, 1).ToString() + " " + sql; } int index = ent.Context.ExecuteStoreCommand(sql, objParams.ToArray()); return index; }
修改,折騰了我不少時間,關鍵就是那個賦值語句,折騰了不少時間,一開始都把時間花費在表達樹上,這也是網上找到的.但看網上的那個修改語句,都是有問題,主要是在修改時,對於參數化的賦值,做不了.只能修改 常量的值,這對我們的使用是有非常大的限制.
后來,突發靈感.想到了,先用表達樹,計算出Expression<Func<T>> updater的值,然后再把那得出來的值,弄成參數,傳進去.就這樣,解決了參數化傳值的問題.
關於這方法,曾經有網友反對過.說直接用sql,就行了.比較簡單. 在這里,我想解釋一下,我堅持要寫,處於2個方面考慮. 一是,方便開發人員開發.因為這個的寫法就是典型的lingq寫法. 二是,我覺的,作為一個框架, 我們要把能統一的東西,統一起來,這樣以后有什么變動,維護起來也比較方便.如果我們直接用sql語句,就會比較亂,不便於后期的維護.
下面我們就看看批量刪除和修改,調用的方便性吧.
ec.testEnt.Update(ent =>ent.MonthlyDataID==new Guid("95134D1D-2647-4F84-B82A-DB84B0BC382E") , ()=> new BMW_MonthlyDataDetail2() { CreationUser = "2012-12-1",CreationDate=DateTime.Parse("2012-10-2"),ModificaitonUser=value }); ec.testEnt.Delete(ent => ent.MonthlyDataID == new Guid("95134D1D-2647-4F84-B82A-DB84B0BC382E"));
看我們刪除和修改是否都很方便啊.?
當然,我這個批量刪除和修改是不支持多表的.因為那個批量刪除和修改多表,用的地方不多,而且實現起來很麻煩.所以就沒有去實現了.
下面我們再看分頁的函數吧.
//分頁 public static IQueryable<T> Page<T, TResult>(this IQueryable<T> query, int pageIndex, int pageSize, Expression<Func<T, TResult>> orderByProperty, bool isAscendingOrder, out int rowsCount) { if (pageSize <= 0) pageSize = 20; rowsCount = query.Count(); if (rowsCount <= pageSize || pageIndex <= 0) pageIndex = 1; int excludedRows = (pageIndex - 1) * pageSize; if (orderByProperty != null) { if (isAscendingOrder) query = query.OrderBy(orderByProperty); else query = query.OrderByDescending(orderByProperty); } if (pageIndex == 1) return query.Take(pageSize); else return query.Skip(excludedRows).Take(pageSize); }
我們把分頁,也用一個函數統一起來,這樣開發人員分頁的時候,就不會每個人都有自己的一套了.
下面我再把這個類的整體代碼弄出來吧.

1 using System; 2 using System.Collections.Generic; 3 using System.Data.Objects; 4 using System.Linq; 5 using System.Linq.Expressions; 6 using System.Text; 7 using System.Threading.Tasks; 8 9 namespace System.Linq 10 { 11 public static class LinqExt 12 { 13 //分頁 14 public static IQueryable<T> Page<T>(this IQueryable<T> query, int pageIndex, int pageSize) 15 { 16 int total; 17 return Page<T>(query, pageIndex, pageSize); 18 } 19 20 //分頁 21 public static IQueryable<T> Page<T>(this IQueryable<T> query, int pageIndex, int pageSize, out int total) 22 { 23 Expression<Func<T, string>> order = null; 24 return Page(query, pageIndex, pageSize, order, false, out total); 25 } 26 27 //分頁 28 public static IQueryable<T> Page<T, TResult>(this IQueryable<T> query, int pageIndex, int pageSize, Expression<Func<T, TResult>> orderByProperty, bool isAscendingOrder, out int rowsCount) 29 { 30 if (pageSize <= 0) pageSize = 20; 31 32 rowsCount = query.Count(); 33 34 if (rowsCount <= pageSize || pageIndex <= 0) pageIndex = 1; 35 36 int excludedRows = (pageIndex - 1) * pageSize; 37 38 if (orderByProperty != null) 39 { 40 if (isAscendingOrder) 41 query = query.OrderBy(orderByProperty); 42 else 43 query = query.OrderByDescending(orderByProperty); 44 } 45 if (pageIndex == 1) 46 return query.Take(pageSize); 47 else 48 return query.Skip(excludedRows).Take(pageSize); 49 } 50 51 52 53 public static int Delete<T>(this ObjectSet<T> ent, Expression<Func<T, bool>> where) where T : class 54 { 55 var query = ent.Where(where); 56 ObjectQuery objQuery = query as ObjectQuery; 57 string sql=objQuery.ToTraceString(); 58 sql = "delete " + sql.Substring(sql.IndexOf("from", StringComparison.OrdinalIgnoreCase)); 59 sql = sql.Replace("[Extent1].", "").Replace("AS [Extent1]", "").Replace("__linq__", ""); 60 List<object> objs = new List<object>(); 61 foreach (var para in objQuery.Parameters) 62 { 63 objs.Add(para.Value); 64 } 65 int index= ent.Context.ExecuteStoreCommand(sql, objs.ToArray()); 66 return index; 67 68 } 69 70 public static int Update<T>(this ObjectSet<T> ent, Expression<Func<T, bool>> where, Expression<Func<T>> updater) where T : class 71 { 72 //where 語句 73 var query = ent.Where(where); 74 ObjectQuery objQuery = query as ObjectQuery; 75 List<object> objParams = new List<object>(); 76 string sql = objQuery.ToTraceString(); 77 sql = sql.Substring(sql.IndexOf("from", StringComparison.OrdinalIgnoreCase)).Replace("__linq__", ""); 78 int paramindex = objQuery.Parameters.Count; 79 foreach (var para in objQuery.Parameters) 80 { 81 objParams.Add(para.Value); 82 } 83 //獲取Update的賦值語句 84 var valueObj = updater.Compile().Invoke(); 85 MemberInitExpression updateMemberExpr = (MemberInitExpression)updater.Body; 86 StringBuilder updateBuilder = new StringBuilder(); 87 Type valueType = typeof(T); 88 foreach (var bind in updateMemberExpr.Bindings.Cast<MemberAssignment>()) 89 { 90 string name = bind.Member.Name; 91 updateBuilder.AppendFormat("{0}=@p{1},", name, paramindex++); 92 var value = valueType.GetProperty(name).GetValue(valueObj); 93 objParams.Add(value); 94 } 95 if (updateBuilder.Length == 0) 96 { 97 throw new Exception("請填寫要更新的值"); 98 } 99 else 100 { 101 sql = " update [Extent1] set " + updateBuilder.Remove(updateBuilder.Length - 1, 1).ToString() + " " + sql; 102 } 103 int index = ent.Context.ExecuteStoreCommand(sql, objParams.ToArray()); 104 return index; 105 106 } 107 108 } 109 }
希望我這個類,對大家有幫助,同時也希望各位網友,提出你們寶貴的意見,讓我們共同進步吧.