使用多映射API时,如果您有除Id“之外的其他键,请确保设置splitOn参数,”splitOn with Multiple relations

时间:2016-10-27 05:20:16

标签: c# asp.net .net orm dapper

当我尝试执行此方法时,我收到以下异常:

  

使用多映射API时,请确保设置splitOn参数if   你有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;
        }

enter image description here

编辑:

我现在通过更改列的顺序来解决问题,如下所示: 但是我想知道我可以做更多的代码增强吗?

 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;
        }

1 个答案:

答案 0 :(得分:5)

您大多误解了Multimapping使用Dapper的工作情况,您的查询会产生以下列:

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

现在在multimapping代码中,以下是您正在调用的精简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")

现在只有一点需要澄清,因为我在评论中发布了years参数,大多数是integer array,对于当前查询都是文本,这样可以正常工作,但不是stored procedures,它使用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中的Parameter类,它可以显式添加参数,以下是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)
    }