3

ORMLite のSqlList機能で Dictionary< 文字列、文字列 > (または文字列、オブジェクト) の一般的なリストを使用しようとしたときに問題が発生した人はいますか?

var data = Db.SqlList<Dictionary<string, string>>("exec my_storedproc p1,p2");

次の例外がスローされます。

Incorrect number of arguments supplied for call to method 
'System.String get_Item(System.String)'

私はまだその中身をデバッグしていませんが、フィールド定義を抽出するときにここでクラッシュするようです:

public static T ConvertTo<T>(this IDataReader dataReader)
    {
        var fieldDefs = ModelDefinition<T>.Definition.AllFieldDefinitionsArray;

注: 基礎となる方言プロバイダーは sqlserver 用です

更新 #1 をさらに掘り下げると、ディクショナリの "String Item" プロパティでクラッシュがトリガーされます。

namespace ServiceStack.OrmLite
public static class PropertyInvoker

    public static PropertyGetterDelegate GetPropertyGetterFn(this PropertyInfo propertyInfo)
    {
    ...
    var exprCallPropertyGetFn = Expression.Call(instanceParam, getMethodInfo);

更新 #2 No_Expressions を使用して OrmLite をコンパイルすると、プロパティ ゲッターが少し異なる方法で返され、フローが通過し、SqlList への呼び出しが正しい数の項目を返します。ただし、各ディクショナリには 0 項目があります。レコードごとに新しい辞書を作成できたようですが、フィールド/列を挿入できませんでした。

考え?

更新 #3 (ハッキングされたソリューション)

興味のある方のために、必要なことを行うために手動で修正を追加しました。OrmLiteReadExtensions では、IsScalar チェックに合わせて「IsDictionary」を追加し、次に ConvertToDictionary を追加しました。私が確信している最もクリーンなソリューションではありませんが、機能します。スニペットは次のとおりです。

public static bool IsDictionary<T>()
    {
        return typeof(IDictionary).IsAssignableFrom(typeof(T));
    }

internal static List<T> SqlList<T>(this IDbCommand dbCmd, string sql, object anonType = null)
    {
        if (anonType != null) dbCmd.SetParameters(anonType, true);
        dbCmd.CommandText = sql;

        using (var dbReader = dbCmd.ExecuteReader())
            return IsScalar<T>()
                    ? dbReader.GetFirstColumn<T>()
                    : IsDictionary<T>() 
                        ? dbReader.ConvertToDictionary<T>() 
                        : dbReader.ConvertToList<T>();
    }

public static List<T> ConvertToDictionary<T>(this IDataReader dataReader)
[...]
while (dataReader.Read())
     {
          var row = CreateInstance<T>();
          var roww = (row as Dictionary<string, object>);
          for (int f = 0; f < fields; f++)
          {
              roww.Add(dataReader.GetName(f), dataReader.GetValue(f));
          }
          to.Add(row);
     }
4

0 に答える 0