高性能數據導入方案&表過濾器&一對多支持篩選- .NET SqlSugar ORM
一、數據導入有哪些難題
1、數據分類
你需要將 插入、更新、忽略不計、錯誤數據 等進么分類匯總,最後返回給客戶,如果沒有很好的設計想把這些操作一步到位非常的難
2、高性能
對於插入或者更新 肯定不能單純的插入或者更新,一定要批量操作,或者用到blukcopy操作
3、數據驗證
對於錯誤數據要進行組裝 ,並返回客戶,讓客戶知道哪些字段 哪個數據出現錯誤
二、使用 Storageable 解決難題
我們可以使用SqlSugar ORM中的 Storageable功能來解決上面的幾大難題 ,SqlSugar 作為老牌ORM框架一直在創新和更新
1、入門示例
如何用Storageable實現簡單的插入或者更新
例題1:導入一個List ,當id等0插入, id>0執行更新 (id是主鍵 )
List<UinitBlukTable> list2 = new List<UinitBlukTable>(); list2.Add(new UinitBlukTable() { Id = 1, Name = "a", Create = DateTime.Now }); list2.Add(new UinitBlukTable() { Id = 2, Name = "a", Create = DateTime.Now }); list2.Add(new UinitBlukTable() { Id = 0, Name = "a", Create = DateTime.Now }); var x = Db.Storageable(list2) .SplitUpdate(it => it.Item.Id > 0) .SplitInsert(it => it.Item.Id == 0).ToStorage(); x.AsInsertable.ExecuteCommand(); x.AsUpdateable.ExecuteCommand();
例題2:導入一個LIST,當Id存在數據執行更新,否則執行插入
var x = Db.Storageable(list2) .SplitUpdate(it => it.Any(y=>y.Id==it.Item.Id))//數據庫存在更新 .SplitInsert(it => true ).ToStorage();//其餘插入 x.AsInsertable.ExecuteCommand(); //也可以使用blukcopy 參考SqlSugar blukcopy用法 x.AsUpdateable.ExecuteCommand();
如果實體沒有主鍵我們可以用
var x = Db.Storageable(list2) .SplitUpdate(it => it.Any(y=>y.Id==it.Item.Id)) .SplitInsert(it => it.NotAny(y => y.Id == it.Item.Id)) .WhereColumns(it=>it.Id).ToStorage(); //以id作為數據庫唯一列,當然支持多個 new {it.id,it.name}
2.數據驗證和統計
準備4條測試數據
List<UinitBlukTable> list2 = new List<UinitBlukTable>(); list2.Add(new UinitBlukTable() { Id = 1, Name = "a", Create = DateTime.Now }); list2.Add(new UinitBlukTable() { Id = 2, Name = "a", Create = DateTime.Now }); list2.Add(new UinitBlukTable() { Id = 3, Name = "a", Create = DateTime.Now.AddYears(-2) }); list2.Add(new UinitBlukTable() { Id = 4, Name ="", Create = DateTime.Now.AddYears(-2) });
編寫代碼將錯誤數據、可插入數據、可更新數據等進行分類
var x = Db.Storageable(list2) .SplitError(it => string.IsNullOrEmpty(it.Item.Name), "名稱不能為空") .SplitError(it => it.Item.Create<DateTime.Now.AddYears(-1),"不是今年的數據") .SplitUpdate(it => it.Any(y=>y.Id==it.Item.Id))//存在更新 .SplitInsert(it => true)//剩餘的插入 .ToStorage(); Console.WriteLine(" 插入 {0} 更新{1} 錯誤數據{2} 不計算數據{3} 刪除數據{4},總共{5}" , x.InsertList.Count, x.UpdateList.Count, x.ErrorList.Count, x.IgnoreList.Count, x.DeleteList.Count, x.TotalList.Count );
執行代碼輸出結果:
我們可以看到其中有1條可以插入的,1條可以更新的,並且2條數據數據
輸出錯誤明細:
foreach (var item in x.ErrorList) { Console.WriteLine("id等於"+item.Item.Id+" : "+item.StorageMessage); }
我們可以看到輸出id3和id4是錯誤的,並且可以輸出具體的錯誤明細
執行更新和插入
x.AsInsertable.ExecuteCommand(); x.AsUpdateable.ExecuteCommand();
三、使用表過濾器
SqlSugar以前也支持了全局過濾器,不過不好用,大部分用戶習慣了以表的方式實現過濾器,用法如下
1、創建表過濾器
SqlSugarClient db = new SqlSugarClient(new ConnectionConfig() { DbType = DbType.SqlServer, ConnectionString = Config.ConnectionString, IsAutoCloseConnection = true }); db.QueryFilter.Add(new TableFilterItem<Order>(it => it.Name.Contains("a"))); //只有表Order才會生效
2、生效的查詢語句
使用了表過濾器後只要帶有order表的查詢語句,都會自動添加一個條件
db.Queryable<Order>().ToList(); //SELECT [Id],[Name],[Price],[CreateTime],[CustomId] FROM [Order] WHERE ([Name] like '%'+@MethodConst0+'%') db.Queryable<OrderItem, Order>((i, o) => i.OrderId == o.Id) .Where(i => i.OrderId != 0) .Select("i.*").ToList(); //SELECT i.* FROM [OrderDetail] i ,[Order] o WHERE ( [i].[OrderId] = [o].[Id] ) AND ( [i].[OrderId] <> @OrderId0 ) AND ([o].[Name] like '%'+@MethodConst1+'%')
3、禁止全局過濾器
db.Queryable<Order>().Filter(null, false).ToList(); //SELECT [Id],[Name],[Price],[CreateTime],[CustomId] FROM [Order]
四、一對多查詢支持條件過濾
sqlsugar對於導航查詢也是支持的越來越好,下面是一對多查詢後在過濾的例子
var list7= Db.Queryable<Order>() .Mapper(it => it.Items, it => it.Items.First().OrderId) .Where(it => it.Items.Any(y => y.ItemId == 1)) //以前只支持.any() .ToList();
五、總結
SqlSugar所有功能都真實來自於客戶,並且是多個客戶共同的需求,其實我並沒有做到什麼創新,只是在客戶的基礎上把他們想要的功能進行了一些設計,如果他們用了不滿意,我在這個基礎上在
慢慢的修改
源碼下載:
//github.com/donet5/SqlSugar sqlsugar已經持續更新6年之久,也越來越完善 ,如果說EF或者完它ORM不更新了,那麼多一個開源就是多一個選擇