Dapper升级SqlSugar问题汇总

最近群里有个小伙伴把Dapper迁移SqlSugar几个不能解决的问题进行一个汇总,我正好写一篇文章来讲解一下

一、sql where in传参问题:

复制代码
  SELECT * FROM users where id IN @ids 

答: SqlSugar中应该是

复制代码
// SELECT * FROM users where id IN (@ids)
var listdb.Ado.SqlQuery<Users>(sql,new {id=new int[]{1,2,3}})  

二、Dapper查询出来的 Dynamic动态类型,支持获取不存在的属性

例如:SELECT UserName FROM users

可以通过 result.UserCode,不会报错

**答:**dynamic expandobject 属性不存在肯定是会报错的 , list[0].id如果不存肯定报错

这个需求还是头一次,因为不报错可能不严谨SQLSugar暂时没有这个方法可以通扩展一个方法实现

复制代码
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了

复制代码
 //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

默认不支持反向转换考虑到数据严谨性,防止线上数据因错误数据导致系统出错

解决方案:加上特性让他支持转换

复制代码
[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)

主要用于结果集返回之后,包装成一个有层次的对象。

Dapper执行ExecuteReader方法之后,还能通过Get<T>("params")获取到。SqlSugar是直接无法获取的,需要包装一次,从DataReaderParameters中获取。

答:

SqlSugar同样可以支持一维对象变成2维对象

复制代码
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; }
}

效果图

image.png