iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 22
3

ExecuteScalar因為其只能讀取第一組結果、第一筆列、第一筆資料特性,是一個常被遺忘的功能,但它在特定需求下還是能派上用場,底下用「查詢資料是否存在」例子來做說明。

首先,Entity Framwork如何高效率判斷資料是否存在?

假如有EF經驗的讀者會答使用Any而不是Count() > 1

使用Count系統會幫轉換SQL為 :

SELECT COUNT(*) AS [value] FROM [表格] AS [t0]

SQL Count 是一個匯總函數,會迭代符合條件的資料行判斷每列該資料是否為null,並返回其行數。

而Any語法轉換SQL使用EXISTS,它只在乎是否有沒有資料,代表不用檢查到每列,只需要其中一筆有資料就有結果,所以效率快。

SELECT 
    (CASE 
        WHEN EXISTS(
            SELECT NULL AS [EMPTY]
            FROM [表格] AS [t0]
            ) THEN 1
        ELSE 0
     END) AS [value]

Dapper如何做到同樣效果?

SQL Server可以使用SQL格式select top 1 1 from [表格] where 條件 搭配 ExecuteScalar 方法,接著在做一個擴充方法,如下 :

public static class DemoExtension
{
  public static bool Any(this IDbConnection cn,string sql,object paramter = null)
  {
    return cn.ExecuteScalar<bool>(sql,paramter);
  }
}

效果圖 :
20191003043825.png

使用如此簡單原因,是利用Dapper ExecuteScalar會去呼叫ExecuteScalarImpl其底層Parse邏輯

private static T ExecuteScalarImpl<T>(IDbConnection cnn, ref CommandDefinition command)
{
    //..略
    object result;
    //..略
    result = cmd.ExecuteScalar();
    //..略
    return Parse<T>(result);
}

private static T Parse<T>(object value)
{
    if (value == null || value is DBNull) return default(T);
    if (value is T) return (T)value;
    var type = typeof(T);
    //..略
    return (T)Convert.ChangeType(value, type, CultureInfo.InvariantCulture);
}

使用 Convert.ChangeType 轉成 bool : 「0=false,非0=true」 特性,讓系統可以簡單轉型為bool值。

注意

不要QueryFirstOrDefault代替,因為它需要在SQL額外做Null的判斷,否則會出現「NullReferenceException」。
20191003043931.png

這原因是兩者Parse實作方式不一樣,QueryFirstOrDefault判斷結果為null時直接強轉型
20191003043941.png

而ExecuteScalar的Parce實作多了為空時使用default值的判斷
20191003043953.png


上一篇
【深入Dapper.NET源碼】 單次、多次 Execute 底層原理
下一篇
【深入Dapper.NET源碼】總結
系列文
🌊 進階學習 ADO.NET、Dapper、Entity Framework 30

尚未有邦友留言

立即登入留言