Dapper迁移SqlSugar问题汇总
最近群里有个小伙伴把Dapper迁移SqlSugar几个不能解决的问题进行一个汇总,我正好写一篇文章来讲解一下
一、sql where in传参问题:
1 | SELECT * FROM users where id IN @ids |
答: SqlSugar中应该是
1 2 | var sql= "SELECT * FROM users where id IN (@ids)" ; //要有()和dapper有差异 var list=db.Ado.SqlQuery<Users>(sql, new {ids= new int []{1,2,3}}) |
二、Dapper查询出来的Dynamic动态类型,支持获取不存在的属性
例如:SELECT UserName FROM users
可以通过 result.UserCode,不会报错
答:dynamic expandobject 属性不存在肯定是会报错的 , list[0].id如果不存肯定报错
这个需求还是头一次,因为不报错可能不严谨SQLSugar暂时没有这个方法
可以通扩展一个方法实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | using System.Collections.Generic; using System.Dynamic; public class ForgivingDynamicObject : DynamicObject { private readonly Dictionary< string , object > _members = new Dictionary< string , object >(); public override bool TryGetMember(GetMemberBinder binder, out object result) { // 尝试从字典中获取成员,如果不存在则返回null return _members.TryGetValue(binder.Name, out result) || (result = null ) != null ; } public override bool TrySetMember(SetMemberBinder binder, object value) { // 将成员设置到字典中 _members[binder.Name] = value; return true ; } } public static class DynamicExtensions { public static ForgivingDynamicObject ToForgivingDynamicObject( this dynamic dynamicObject) { var forgivingObject = new ForgivingDynamicObject(); if (dynamicObject is IDictionary< string , object > dictionary) { foreach ( var kvp in dictionary) { forgivingObject.TrySetMember( new SetMemberBinder(kvp.Key, false ), kvp.Value); } } return forgivingObject; } } dynamic expando = new ExpandoObject(); expando.ExistingProperty = "Hello" ; // 转换为 ForgivingDynamicObject ForgivingDynamicObject forgivingObj = expando.ToForgivingDynamicObject(); // 访问存在的属性 string value = forgivingObj.ExistingProperty; // "Hello" // 访问不存在的属性,将返回null而不是抛出异常 string nonExistingValue = forgivingObj.NonExistingProperty; // null |
三、表值参数必须传typeName
Dapper是可以不用传的
Sqlsugar在5.4.1.152+ 下面value可以传null了
1 2 3 | //SqlSugar中用法 var s = new SugarParameter( "@p" , value); s.TypeName = "dtTableName" ; |
四、类型转换:在Dapper中很多类型做了兼容处理。
比如:数据库中是string,但值是int SELECT CAST( id as nvarchar) id FROM users
Dapper中Query实体时,id允许定义为string,
答:Sqlsugar中类型只支持int转string,不支持string转int
默认不支持反向转换考虑到数据严谨性,防止线上数据因错误数据导致系统出错
解决方案:加上特性让他支持转换
1 2 | [SugarColumn(SqlParameterDbType= typeof (CommonPropertyConvert))] //ORM自带的也支持重写这个转换类 public DateTime DcValue { get ; set ; } |
五、Dapper 联表VO转换
l 不支持IEnumerable<TReturn> Query<TFirst, TSecond, TReturn>(string sql, Func<TFirst, TSecond, TReturn> map, object? param = null, IDbTransaction? transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null) =>
MultiMap<TFirst, TSecond, DontMap, DontMap, DontMap, DontMap, DontMap, TReturn>(cnn, sql, map, param, transaction, buffered, splitOn, commandTimeout, commandType)
主要用于结果集返回之后,包装成一个有层次的对象。
答:
SqlSugar同样可以支持一维对象变成2维对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | var list=db.SqlQueryable<SQLVO>( "select 1 as id,'jack' as name " ).ToList(); public class SQLVO { [SugarColumn(IsOwnsOne = true )] public ITEM1 ITEM1 { get ; set ; } //item1和item2不能有重复字段 [SugarColumn(IsOwnsOne = true )] public ITEM2 ITEM2 { get ; set ; } //item1和item2不能有重复字段 } public class ITEM1 { public int ID { get ; set ; } } public class ITEM2 { public string Name { get ; set ; } } |
效果图
六、 获取Output
Dapper执行ExecuteReader方法之后,还能通过Get<T>(“params”)获取到。SqlSugar是直接无法获取的,需要包装一次,从DataReaderParameters中获取。
答: 暂时没有get方法可以通索引拿出来
//我们还可以用 GetParameters 来简化参数操作 SugarParameter [] pars =db.Ado.GetParameters(new{p=1,p2=p}); pars[1].Direction=ParameterDirection.Output; db.Ado.ExecuteCommand(sql,pars); var outValue=pars[1].Value;
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· NetPad:一个.NET开源、跨平台的C#编辑器