最近羣裏有個小夥伴把Dapper遷移SqlSugar幾個不能解決的問題進行一個彙總,我正好寫一篇文章來講解一下
一、sql where in傳參問題:
SELECT * FROM users where id IN @ids
答: SqlSugar中應該是
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暫時沒有這個方法
可以通擴展一個方法實現
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)
主要用於結果集返回之後,包裝成一個有層次的對象。
答:
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; } }
效果圖
六、 獲取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;