2016-10-27 5 views
2

で「」あなたはID以外のキーを持っている場合は、splitOnのPARAMを設定することを確認splitOnをマルチマッピングAPIを使用している場合、私は、このメソッドを実行しようとすると、私は次の例外を取得:複数の関係

マルチマッピングAPIを使用すると、ID以外のキーを持っている 場合は


public static IEnumerable<FinancePositionList> GetFinancialListsForConsecutiveYears(int year, int periodTypeId, int period) 
     { 
      IEnumerable<FinancePositionList> resultList; 
      using (var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["Finance"].ConnectionString)) 
      { 
       conn.Open(); 
       StringBuilder query = new StringBuilder(); 
       query.Append("SELECT b.CompanyId,b.CompanyName,[Year]"); 
       query.Append(",CreationDate,AccruedExpenses,AdvancePaymentsToContractors"); 


       query.Append("FROM finance.FinanceList a INNER JOIN finance.Company b "); 
       query.Append("ON a.CompanyId = b.CompanyId "); 
       query.Append("INNER JOIN finance.ListPeriod c "); 
       query.Append("ON c.FinanceListId = a.FinanceListId "); 
       query.Append("WHERE Discriminator = " + "'" + "FinancePositionList" + "' "); 
       query.Append("AND[Year] IN @years "); 
       query.Append("AND c.PeriodTypeId = @PeriodTypeId AND c.Period = @Period "); 
       query.Append("ORDER BY b.CompanyId, a.[Year] DESC "); 

       resultList = conn.Query<FinancePositionList, Company,ListPeriod, FinancePositionList>(query.ToString(), 
        (a, b,c) => 
        { 
         a.Company = b; 
         c.FinanceList = a; 
         return a; 
        }, 
        new 
        { 
         years = new[] { year, year - 1 }, 
         PeriodTypeId = periodTypeId, 
         Period = period 
        }, 
        splitOn: "CompanyId,FinanceListId").AsEnumerable(); 
      } 
      return resultList; 
     } 

」splitOnのPARAMを設定することを確認します3210

enter image description here


EDIT:

は、私は次のように列の順序を変更することで、問題解決: をしかし、私はより多くの機能拡張がコードに存在する場合、私は何ができるだろうか?あなたはほとんどDapperを使用してMultimappingの作業を誤解している

public static IEnumerable<FinancePositionList> GetFinancialListsForConsecutiveYears(int year, int periodTypeId, int period) 
     { 
      IEnumerable<FinancePositionList> resultList; 
      using (var conn = new SqlConnection(ResolveConnectionString())) 
      { 
       conn.Open(); 
       StringBuilder query = new StringBuilder(); 
       query.Append("SELECT CreationDate,AccruedExpenses,AdvancePaymentsToContractors,[Year]"); 
       query.Append(",b.CompanyId,b.CompanyName,c.FinanceListId "); 
       query.Append("FROM finance.FinanceList a INNER JOIN finance.Company b "); 
       query.Append("ON a.CompanyId = b.CompanyId "); 
       query.Append("INNER JOIN finance.ListPeriod c "); 
       query.Append("ON c.FinanceListId = a.FinanceListId "); 
       query.Append("WHERE Discriminator = " + "'" + "FinancePositionList" + "' "); 
       query.Append("AND [Year] IN @years "); 
       query.Append("AND c.PeriodTypeId = @PeriodTypeId AND c.Period = @Period "); 
       query.Append("ORDER BY b.CompanyId, a.[Year] DESC "); 

       resultList = conn.Query<FinancePositionList, Company, ListPeriod, FinancePositionList>(query.ToString(), 
        (a, b, c) => 
        { 
         a.Company = b; 
         a.CompanyId = b.CompanyId; 
         a.FinanceListId = c.FinanceListId; 
         return a; 
        }, 
        new 
        { 
         years = new[] { year, year - 1 }, 
         PeriodTypeId = periodTypeId, 
         Period = period 
        }, 
        splitOn: "CompanyId,FinanceListId").AsEnumerable(); 
      } 
      return resultList; 
     } 

答えて

3

、あなたのクエリには、次の列が得られます

**"CompanyId","CompanyName","Year","CreationDate","AccruedExpenses", 
"AdvancePaymentsToContractors"** 

を今すぐmultimappingコードで、次はあなたが呼び出しているDapperのQuery過負荷であります(source codeからチェック):

public static IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TReturn>(
this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TReturn> map, 
object param, IDbTransaction transaction, bool buffered, string splitOn, 
int? commandTimeout, CommandType? commandType) 

私は誤解します全体的な呼び出しを訂正しましたが、現時点では、すでに修正済みのSplitOnを使用するマルチマッピングタイプのマッピングでのみ問題が発生するため、splitonの列がクエリ結果で利用可能であれば、

私はコメントで投稿しているよう
conn.Query<FinancePositionList, Company,ListPeriod, FinancePositionList>(query.ToString(), (a, b,c) => 
        { 
         a.Company = b; 
         c.FinanceList = a; 
         return a; 
        }, 
        new 
       { 
        years = new[] { year, year - 1 }, 
        PeriodTypeId = periodTypeId, 
        Period = period 
       }, splitOn: "CompanyId,FinanceListId") 

今だけのポイントは、なくstored proceduresため、ほとんどinteger arrayは、すべてのテキストである現在のクエリのために、これは正常に動作しますyearsパラメータ、の作業をされて解明されないままでありますDataTableを使用して同じものが期待される場所では、コレクションと同じ列と列の名前はTable Valued Parameters。私は、現在のユースケースに必要な変更はこれ以上見込めません。

編集匿名パラメータと動的パラメータの例を提供する:

AnonymousParameters

C#でこの単純な匿名型、hereをチェックし、アイデアは、あなたが簡単なプレースホルダを使用してすべてのパラメータを供給することができています{max = <value>,min=<value>}のように、または名前が{max,min}と一致していても、どちらの場合でもパラメータは@max@minです。大文字と小文字は関係ありません。あなたのコードではAnonymousParametersを使用していますメートルyears, PeriodTypeId, Period、それは内部的にタイプやその他の詳細を推測し、すべてが入力パラメータであることを前提となり

{years = new[] { year, year - 1 },PeriodTypeId = periodTypeId,Period = period} 

動的パラメータ

彼らはそれ以上にあなたを取得Ado.Netにおけるパラメータのクラス、のようなものです明示的にパラメータを追加し、次はDapperのコードでオーバーロードされ、明示的などType, Directionのように(dapperソースコードからコードスニペットを)すべての情報を提供する必要があります。

public partial class DynamicParameters : SqlMapper.IDynamicParameters, SqlMapper.IParameterLookup, SqlMapper.IParameterCallbacks 
    { 
    public void Add(string name, object value, DbType? dbType, ParameterDirection? direction, int? size) 

    public void Add(string name, object value = null, DbType? dbType = null, ParameterDirection? direction = null, int? size = null, byte? precision = null, byte? scale = null) 
    } 
+0

ありがとう、ええ、これは私が推奨した 'Dapper'を初めて使う時です。私は私のパラメータを渡す方法を '最初に'使うのであればここに質問があります。私がここでやりたいことは、クエリを実行することです。複数の結合がパラメータを渡すことを許可しています。 –

+1

パラメータは匿名型または動的パラメータを使用して簡単に行うことができますが、入力パラメータに制限されていますが、匿名型を使用することをお勧めします。@ https://github.com/StackExchange/dapper-dot-net の例をチェックするか、ソースコードは、使用法を理解するための良いテストケースを持っています –

+0

あなたのアイデアを明確にするためにクエリを書き直すことができます –