ExecuteScalar因為其只能讀取第一組結果、第一筆列、第一筆資料
特性,是一個常被遺忘的功能,但它在特定需求下還是能派上用場,底下用「查詢資料是否存在」例子來做說明。
假如有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]
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);
}
}
效果圖 :
使用如此簡單原因,是利用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」。
這原因是兩者Parse實作方式不一樣,QueryFirstOrDefault判斷結果為null時直接強轉型
而ExecuteScalar的Parce實作多了為空時使用default值
的判斷