高性能数据导入方案&表过滤器&一对多支持筛选- .NET SqlSugar ORM
一、数据导入有哪些难题
该功能可以说100%的开发人员都会遇到,并且非常的常见,比如批量操作,你知道哪条数据错了吗?
你都不知道客户更不知道了
1、数据分类
你需要将 插入、更新、忽略不计、错误数据 等进么分类汇总,最后返回给客户,如果没有很好的设计想把这些操作一步到位非常的难
2、高性能
对于插入或者更新 肯定不能单纯的插入或者更新,一定要批量操作,或者用到blukcopy操作
3、数据验证
对于错误数据要进行组装 ,并返回客户,让客户知道哪些字段 哪个数据出现错误
二、使用 Storageable 解决难题
我们可以使用SqlSugar ORM中的 Storageable功能来解决上面的几大难题 ,SqlSugar 作为老牌ORM框架一直在创新和更新
1、入门示例
如何用Storageable实现简单的插入或者更新
例题1:导入一个List ,当id等0插入, id>0执行更新 (id是主键 )
1 2 3 4 5 6 7 8 9 10 | 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存在数据库执行更新,否则执行插入
1 2 3 4 5 | 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(); |
如果实体没有主键我们可以用
1 2 3 4 | 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条测试数据
1 2 3 4 5 | 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) }); |
编写代码将错误数据、可插入数据、可更新数据等进行分类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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条错误数据
输出错误明细:
1 2 3 4 | foreach ( var item in x.ErrorList) { Console.WriteLine( "id等于" +item.Item.Id+ " : " +item.StorageMessage); } |
我们可以看到输出id3和id4是错误的,并且可以输出具体的错误明细
执行更新和插入
1 2 | x.AsInsertable.ExecuteCommand(); x.AsUpdateable.ExecuteCommand(); |
三、使用表过滤器
SqlSugar以前也支持了全局过滤器,不过不好用,大部分用户习惯了以表的方式实现过滤器,用法如下
1、创建表过滤器
1 2 | 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表的查询语句,都会自动添加一个条件
1 2 3 4 5 6 7 | 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、禁止全局过滤器
1 2 | db.Queryable<Order>().Filter( null , false ).ToList(); //SELECT [Id],[Name],[Price],[CreateTime],[CustomId] FROM [Order] |
四、一对多查询支持条件过滤
sqlsugar对于导航查询也是支持的越来越好,下面是一对多查询后在过滤的例子
1 2 3 4 | 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所有功能都真实来自于客户,并且是多个客户共同的需求,其实我并没有做到什么创新,只是在客户的基础上把他们想要的功能进行了一些设计,如果他们用了不满意,我在这个基础上在
慢慢的修改
源码下载:
https://github.com/donet5/SqlSugar sqlsugar已经持续更新6年之久,也越来越完善 ,如果说EF或者其它ORM不更新了,那么多一个开源就是多一个选择
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?