Dapper: le API multi-mapping ti assicurano di impostare splitOn

Aug 27 2020

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

2 Steve Aug 27 2020 at 04:48

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.