2013-03-15 167 views
3

我一直在使用Dapper.NET一段時間了。我只是想知道是否可以讓Dapper修剪字符串,因爲它將它們分配給對象的屬性。修剪字符串與Dapper.NET

我目前在屬性設置器中使用SQL中的LTRIM(RTRIM(fieldname))和/或value.Trim()

但是我使用的是使用字符而不是varchar的遺留數據庫,我想知道是否有辦法減少我不得不修剪所有內容的時間。

我有一個通過編輯短小精悍的源代碼,自己去了,但最終打破其他映射等這麼屈服了。

如果任何人有可能減少這方面的開銷有任何建議只是想知道。 (我可能會錯過一些非常簡單的東西!)

我正在用C#3.5順便說一句。

+0

什麼數據庫你在使用它的'傳統名稱'訪問? Interbase的? ...等 – MethodMan 2013-03-15 15:56:00

+0

道歉,其實際MS SQL服務器。 – Moffmo 2013-03-15 16:14:29

+0

那麼你是在尋找一個全面的屬性設置器,但是在服務器上的LTRIM(RTRIM(...))的性能,使得查詢每次都會在服務器端自動修剪? – Todd 2013-03-16 03:48:17

回答

6

我不喜歡小巧玲瓏修改的想法直。我決定通過創建一個擴展方法來解決Dapper的問題,並僅僅反映結果並修剪所有字符串屬性來解決問題。

public static class DapperExtensions { 
    public static IEnumerable<T> Query<T>(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null) { 
     var dapperResult = SqlMapper.Query<T>(cnn, sql, param, transaction, buffered, commandTimeout, commandType); 
     var result = TrimStrings(dapperResult.ToList()); 
     return result; 
    } 

    static IEnumerable<T> TrimStrings<T>(IList<T> objects) { 
     //todo: create an Attribute that can designate that a property shouldn't be trimmed if we need it 
     var publicInstanceStringProperties = typeof (T).GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => x.PropertyType == typeof (string) && x.CanRead && x.CanWrite); 
     foreach (var prop in publicInstanceStringProperties) { 
      foreach (var obj in objects) { 
       var value = (string) prop.GetValue(obj); 
       var trimmedValue = value.SafeTrim(); 
       prop.SetValue(obj, trimmedValue); 
      } 
     } 
     return objects; 
    } 

    static string SafeTrim(this string source) { 
     if (source == null) { 
      return null; 
     } 
     return source.Trim(); 
    } 
} 

至關重要的我的解決方案(因爲我想用相同的名稱小巧玲瓏)是擴展方法的分辨率是如何工作的,你可以閱讀有關here

+0

我不敢相信我其實沒有想到這個!我實際上也爲自己實施了自己的包裝,但還有其他的東西。我沒有想到在那裏做字符串修剪! – Moffmo 2015-04-27 08:44:46

1

我假設您想要一種更自然的方式來通過您的POCO暗示LTRIM(RTRIM())函數,以便您不必每次都要手動輸入LTRIM(RTRIM())時該字段,無需手動重複勞動即可爲您提供SQL性能。

我對你有兩種選擇:

在小巧玲瓏的 - 點 - 網側:

你可以就在查詢功能階段添加一些代碼,對原始SQL執行替換算法查詢。

  • 如果您在查詢多個表,我會考慮這一點的範圍
  • 否則,我相信這可以很容易不破壞短小精悍引擎的其餘部分來完成。

過程:

  • 首先在你的表名執行一個無知的IndexOf,不區分大小寫,因此您可以通過通做一個快速的,如果它不是。
  • 如果找到表名,那麼執行一些更可靠的查詢分析,確保您發現的表名實際上是查詢中的表名。在這裏,您還可以確保查詢中只有一個表並且沒有連接。
  • 如果在Select a *,這可以擴展到基於你的POCO定義
  • 所以,現在你只要在你的選擇陣容
  • 對於所有字段的字段的字段名,在選擇陣容,發現在你的POCO定義,那裏是一個[裁剪]屬性的名稱,以及LTRIM(RTRIM({字段名}))爲[{字段名}]替換字段名

在SQL端:

如果您有權創建在服務器上的視圖,然後你可以編寫一個存儲過程來創建/更改(更新)一組視圖,這些視圖暴露了char字段的varchar接口。

批量更新 - 運行這個每次有一個架構的變化:1。 遍歷所有用戶表 2.創建或更新相應的視圖

UpdateTableView(表名): 1.退出,如果沒有焦炭領域 2,自動化創建的視圖與投(LTRIM(RTRIM(..))爲varchar(CHAR_FIELD_SIZE)

+0

感謝Todd的建議。一定會試一試。我們的很多查詢都使用多個表。但是,如果我們使用了可以工作的觀點。我不確定這會影響它的性能。將嘗試,看看它是如何去! – Moffmo 2013-03-18 11:15:53

+0

RE:Views - 通常意見可以使表現更好。物化視圖允許您在視圖上也創建索引。確保何時有模式更改可以「刷新」視圖。某些ORM可能無法通過視圖回寫,特別是如果缺少ID。 – Todd 2013-03-19 00:00:27

1

馬特,

這可以很容易的。我做了這個變化來清潔SQL char空間,我已經測試過它如果由於變化導致速度緩慢,我的代碼不會顯示任何跡象。

第一個確保您備份您的退出源代碼,以便在您需要時更容易恢復。

下一頁創建以下方法:

public static string ReadString(object value) /*** CUSTOM CODE ***/ 
{ 
    if (value == null || value is DBNull) return null; 
    return value.ToString().Trim(); 
} 

我總是刻度/ *自定義代碼我所有的代碼更改* /讓我以後可以很容易地找到我的變化

下一頁找到以下方法:

public static void SetTypeMap(Type type, ITypeMap map) 

現在這種方法找到以下行:

if (memberType == typeof (char) || memberType == typeof (char?)) 
{ 
    il.EmitCall(OpCodes.Call, typeof (SqlMapper).GetMethod(
     memberType == typeof (char) ? "ReadChar" : "ReadNullableChar", 
     BindingFlags.Static | BindingFlags.Public), null); 
     // stack is now [target][target][typed-value] 
} 
else 

,並修改爲:

if (memberType == typeof (char) || memberType == typeof (char?)) 
{ 
    il.EmitCall(OpCodes.Call, typeof (SqlMapper).GetMethod(
     memberType == typeof (char) ? "ReadChar" : "ReadNullableChar", 
     BindingFlags.Static | BindingFlags.Public), null); 
     // stack is now [target][target][typed-value] 
} 
else if (memberType == typeof(string)) /*** CUSTOM CODE START ***/ 
{ 
    il.EmitCall(OpCodes.Call, typeof(SqlMapper).GetMethod("ReadString", BindingFlags.Static | BindingFlags.Public), null); 
    // stack is now [target][target][typed-value] 
} /*** CUSTOM CODE END ***/ 
else 

編譯,你準備好去

+0

這太棒了。我也嘗試過編輯SetTypeMap,但是我真的不知道我在用Emit Calls做什麼,而且我也無法弄清楚在哪裏處理字符串字段。我不能相信你所要做的就是添加另一個! – Moffmo 2014-04-28 13:50:19