Dapper - Les API multi-mapping vous garantissent de définir le splitOn

Aug 27 2020

Pour le code ci-dessous, j'obtiens le message d'erreur suivant.

*** Erreur ***

Lorsque vous utilisez les API multi-mapping, assurez-vous de définir le paramètre splitOn si vous avez des clés autres que Id (paramètre 'splitOn')

D'après ce que j'ai compris, je transmets le paramètre splitOn, est-ce que je manque quelque chose d'évident?

Code


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


Mettre à jour

Code Proc stocké


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


Réponses

2 Steve Aug 27 2020 at 04:48

Je n'ai pas vos données, mais je pense que vous devriez changer votre code de cette façon

// 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 ne construira pas et ne passera pas une liste de LookUpValue directement, mais il parcourra les enregistrements en créant les objets à partir de chaque enregistrement retourné et en passant ces objets un par un à l'expression lambda.
Votre expression lambda peut utiliser un Dictionary pour stocker chaque objet LookupTable reçu et ajouter l'objet LookupValue à sa propriété. Lorsque Dapper termine son itération sur l'enregistrement, vos objets sont stockés dans la collection Values ​​du dictionnaire

Bien sûr, cela suppose que votre classe LookUpTable a une List<LookUpValue>propriété

public class LookupTable
{
    public int LookupValueID { get; set; }
    .... other properties ....
    public List<LookUpValue> LookUpValues {get;set} = new List<LookUpValue>();
}

Notez comment la propriété crée la liste lors de l'initialisation pour éviter une logique complexe dans l'expression lambda Dapper.