Dapper: le API multi-mapping ti assicurano di impostare splitOn
Per il codice mostrato di seguito, ricevo il seguente messaggio di errore.
*** Errore ***
Quando si utilizzano le API multi-mapping assicurarsi di impostare il parametro splitOn se si dispone di chiavi diverse da Id (parametro 'splitOn')
Da quello che ho capito sto passando il parametro splitOn mi manca qualcosa di ovvio?
Codice
using (var connection = new Microsoft.Data.SqlClient.SqlConnection(connectionString))
{
connection.Open();
LookupTables = connection.Query<LookupTable, List<LookupValue>, LookupTable>("exec [lookups].[SelAllLookupTable]",
(lookuptable, lookupvalue) => {
lookuptable.LookUpValues = lookupvalue.ToList<LookupValue>();
return lookuptable;
}, splitOn: "LookupValueID").ToList();
}
Aggiornare
Codice procedura memorizzato
ALTER PROCEDURE [lookups].[SelAllLookupTable]
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
SELECT lt.[LookupTableID],
lt.[GUID],
lt.[CreatedBy],
lt.[CreatedOn],
lt.[UpdatedBy],
lt.[UpdatedOn],
lt.[ChangeReason],
lt.[Name],
lt.[Description],
lv.[LookupValueID],
lv.[LookupTableID],
lv.[GUID],
lv.[CreatedBy],
lv.[CreatedOn],
lv.[UpdatedBy],
lv.[UpdatedOn],
lv.[ChangeReason],
lv.[Description],
lv.[DisplayOrderNo]
FROM lookups.LookupTable lt
LEFT JOIN lookups.LookupValue lv ON lt.LookupTableID = lv.LookupTableID
END
Risposte
Non ho i tuoi dati, ma penso che dovresti cambiare il tuo codice in questo modo
// Where we store the distinct LookUpTable found by the query
Dictionary<int, LookUpTable> result = new Dictionary<int, LookUpTable>();
using (var connection = new Microsoft.Data.SqlClient.SqlConnection(connectionString))
{
connection.Open();
var LookupTables = connection.Query<LookupTable, LookUpValue, LookupTable>("exec [lookups].[SelAllLookupTable]",
(lkt, lkv) =>
{
// Check if we have the instance already in the dictionary
// add it if not,
if (!result.ContainsKey(lkt.LookUpTableID))
result.Add(lkt.LookUpTableID, lkt);
result[lkt.LookupTableID].LookUpValues.Add(lkv);
return lkt;
}, splitOn: "LookupValueID").ToList();
}
return result.Values.ToList();
Dapper non costruirà e passerà direttamente un elenco di LookUpValue, ma itererà sui record creando gli oggetti da ciascun record restituito e passando questi oggetti uno per uno all'espressione lambda.
La tua espressione lambda potrebbe utilizzare un dizionario per archiviare ogni oggetto LookupTable ricevuto e aggiungere l'oggetto LookupValue alla relativa proprietà. Quando Dapper termina la sua iterazione sul record, i tuoi oggetti vengono archiviati nella raccolta Values del dizionario
Ovviamente questo presuppone che la tua classe LookUpTable abbia una List<LookUpValue>proprietà
public class LookupTable
{
public int LookupValueID { get; set; }
.... other properties ....
public List<LookUpValue> LookUpValues {get;set} = new List<LookUpValue>();
}
Si noti come la proprietà crea l'elenco all'inizializzazione per evitare una logica complessa nell'espressione lambda Dapper.