J'obtiens l'exception suivante lorsque j'essaie d'exécuter cette méthode:
Lorsque vous utilisez les API de mappage multiple, assurez-vous de définir le paramètre splitOn si vous avez des clés autres que 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;
}
MODIFIER :
Je résous le problème maintenant en changeant l'ordre des colonnes comme ceci: Mais je me demande s'il est possible d'améliorer le code?
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;
}
Vous avez surtout mal compris le fonctionnement du Multimapping
aide de Dapper
, Votre requête donne les colonnes suivantes:
**"CompanyId","CompanyName","Year","CreationDate","AccruedExpenses",
"AdvancePaymentsToContractors"**
Maintenant, dans le code multimapping
, voici la surcharge de Query
dapper que vous appelez (vérifiée à partir du 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)
Auparavant, j'ai mal compris l'appel global, mais maintenant, il semble que le problème ne concerne que le mappage de type Multi mapping à l'aide de SplitOn , que vous avez déjà corrigé, par conséquent, ce qui suit fonctionnerait, à condition que les colonnes de spliton
correctes soient disponibles dans le résultat de la requête
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")
Maintenant, seul point reste à clarifier car j'ai posté dans le commentaire fonctionne le paramètre des years
, qui est principalement un integer array
, pour la requête actuelle qui est entièrement en texte, cela fonctionnerait bien, mais pas pour les stored procedures
, où cela se produirait. attendez-vous à la même utilisation de DataTable
, avec la même séquence et le même nom de colonnes que la collection ne peut être fournie qu'en utilisant les Table Valued Parameters
. Je ne prévois plus de modification requise pour le cas d'utilisation actuel.
Modifiez pour fournir un exemple de paramètres anonymes et de paramètres dynamiques:
AnonymousParameters
Ce type anonyme simple en C #, vérifiez ici , l'idée est que vous pouvez fournir tous les paramètres en utilisant un espace réservé simple comme {max = <value>,min=<value>}
ou même tel quel si le nom correspond à {max,min}
, dans les deux paramètres de cas sont @max
et @min
, la casse n'a pas d'importance, vous utilisez les paramètres AnonymousParameters
dans votre code pour les paramètres years, PeriodTypeId, Period
, il en déduira le type et d'autres détails en interne et supposerait que tout soit entré paramètres
{years = new[] { year, year - 1 },PeriodTypeId = periodTypeId,Period = period}
Paramètres dynamiques
Ils sont plus comme la classe des paramètres dans Ado.Net, vous accéderez à ajouter un paramètre explicitement, après les surcharges dans le code Dapper, vous devez fournir toutes les informations comme le Type, Direction
etc explicitement (extrait de code de pimpant code source) :
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)
}