3

私はDapper.NETしばらくの間使用しています。オブジェクトのプロパティに文字列を割り当てるときに、Dapper で文字列をトリミングできるかどうか疑問に思っていました。

現在LTRIM(RTRIM(fieldname))、SQL および/またはvalue.Trim()プロパティ セッターで使用しています。

ただし、varchar の代わりに chars を使用する従来のデータベースを使用しているため、すべてをトリミングする時間を短縮する方法があるかどうか疑問に思っていました。

私はdapperのソースコードを編集して自分で試してみましたが、他のマッピングなどを壊してしまい、諦めました.

このオーバーヘッドを削減できる提案があるかどうか疑問に思いました。(非常に単純なものが欠けている可能性があります!)

ところで、私はC#3.5で作業しています。

4

3 に答える 3

7

Dapper を直接変更するという考えは好きではありませんでした。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();
    }
}

私のソリューションにとって重要なのは (Dapper と同じ名前を使用したかったため)、拡張メソッドの解決がどのように機能するかです

于 2015-04-10T00:11:38.107 に答える
1

マット、

これは非常に簡単に行うことができます。SQL char スペースを消去するためにこの変更を行いました。私はそれをテストしましたが、私のコードは、変更による遅さの兆候を示していません。

最初に、既存のソース コードをバックアップして、必要な場合に簡単に元に戻せるようにしてください。

次に、次のメソッドを作成します。

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

コードの変更はすべて / * CUSTOM CODE * /でマークするので、後で変更を簡単に見つけることができます。

次に、次のメソッドを見つけます。

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

コンパイルすれば準備完了

于 2014-04-26T20:42:13.313 に答える
1

そのフィールドを返すたびに LTRIM(RTRIM()) を手動で入力する必要がないように、POCO を介して LTRIM(RTRIM()) 関数を暗示するより自然な方法が必要であると想定しています。手動の繰り返し作業なしで SQL パフォーマンスを実現します。

2 つのオプションがあります。

Dapper-Dot-Net 側:

クエリ関数の段階でコードを追加して、生の SQL クエリで置換アルゴリズムを実行できます。

  • クエリに複数のテーブルがある場合、これは範囲外と考えます
  • それ以外の場合は、dapper エンジンの残りの部分を中断することなく、これを非常に簡単に実行できると思います。

プロセス:

  • 最初にテーブル名に対して無知な IndexOf を実行し、大文字と小文字を無視して、そうでない場合はすばやくパススルーできるようにします。
  • テーブル名が見つかった場合は、クエリのより信頼性の高い分析を実行し、見つかったテーブル名が実際にクエリのテーブル名であることを確認します。ここでは、クエリにテーブルが 1 つだけあり、結合がないことも確認できます。
  • 選択に * がある場合、これは poco 定義に基づいてフィールド名に展開できます
  • これで、選択したラインナップにフィールドができました
  • すべてのフィールドについて、選択したラインナップで、[Trim] 属性がある poco 定義で名前を見つけ、フィールド名を [{FieldName}] として LTRIM(RTRIM({FieldName})) に置き換えます。

SQL 側:

サーバー上でビューを作成する権限がある場合は、ストアド プロシージャを記述して、char フィールドの varchar インターフェイスを公開する一連のビューを作成/変更 (更新) できます。

バッチ更新 - スキーマが変更されるたびにこれを実行します。 1. すべてのユーザー テーブルをループします。 2. 対応するビューを作成または更新します。

UpdateTableView(tableName): 1. char フィールドがない場合は終了します 2. cast(LTRIM(RTRIM(..)) を varchar(CHAR_FIELD_SIZE) として使用してビューの作成を自動化します

于 2013-03-16T04:03:48.860 に答える