Utilisation correcte du Multimapping dans Dapper

dapper

Question

J'essaie d'utiliser la fonctionnalité Multimapping de dapper pour renvoyer une liste de produits et de clients associés.

[Table("Product")]
public class ProductItem
{
    public decimal ProductID { get; set; }        
    public string ProductName { get; set; }
    public string AccountOpened { get; set; }
    public Customer Customer { get; set; }
} 

public class Customer
{
    public decimal CustomerId { get; set; }
    public string CustomerName { get; set; }
}

Mon code dapper est comme suit

var sql = @"select * from Product p 
            inner join Customer c on p.CustomerId = c.CustomerId 
            order by p.ProductName";

var data = con.Query<ProductItem, Customer, ProductItem>(
    sql,
    (productItem, customer) => {
        productItem.Customer = customer;
        return productItem;
    },
    splitOn: "CustomerId,CustomerName"
);

Cela fonctionne bien mais il me semble que je dois ajouter la liste complète des colonnes au paramètre splitOn pour renvoyer toutes les propriétés des clients. Si je n'ajoute pas "CustomerName", il renvoie null. Est-ce que je ne comprends pas la fonctionnalité de base de la fonctionnalité multimapping. Je ne veux pas avoir à ajouter une liste complète des noms de colonnes à chaque fois.

Réponse acceptée

Je viens de faire un test qui fonctionne bien:

var sql = "select cast(1 as decimal) ProductId, 'a' ProductName, 'x' AccountOpened, cast(1 as decimal) CustomerId, 'name' CustomerName";

var item = connection.Query<ProductItem, Customer, ProductItem>(sql,
    (p, c) => { p.Customer = c; return p; }, splitOn: "CustomerId").First();

item.Customer.CustomerId.IsEqualTo(1);

Le paramètre splitOn doit être spécifié en tant que point de partage, la valeur par défaut étant Id. S'il existe plusieurs points de partage, vous devrez les ajouter dans une liste délimitée par des virgules.

Disons que votre jeu d'enregistrements ressemble à ceci:

ProductID | ProductName | AccountOpened | CustomerId | CustomerName 
---------------------------------------   -------------------------

Dapper doit savoir comment diviser les colonnes dans cet ordre en 2 objets. Un aperçu rapide indique que le client démarre à la colonne CustomerId , donc splitOn: CustomerId .

Il y a une grande mise en garde ici, si l'ordre des colonnes dans la table sous-jacente est retourné pour une raison quelconque:

ProductID | ProductName | AccountOpened | CustomerName | CustomerId  
---------------------------------------   -------------------------

splitOn: CustomerId entraînera un nom de client nul.

Si vous spécifiez CustomerId,CustomerName tant que points de partage, dapper suppose que vous essayez de diviser le jeu de résultats en 3 objets. La première commence au début, la seconde commence à CustomerId , la troisième à CustomerName .


Réponse populaire

Nos tables sont nommées de la même manière que la vôtre, où quelque chose comme "CustomerID" peut être retourné deux fois en utilisant une opération "select *". Par conséquent, Dapper fait son travail mais se divise trop tôt (peut-être), car les colonnes seraient:

(select * might return):
ProductID,
ProductName,
CustomerID, --first CustomerID
AccountOpened,
CustomerID, --second CustomerID,
CustomerName.

Cela rend le paramètre spliton: pas très utile, surtout lorsque vous ne savez pas dans quel ordre les colonnes sont renvoyées. Bien sûr, vous pouvez spécifier manuellement les colonnes ... mais c'est en 2017 et nous faisons rarement cela pour les objets de base.

Ce que nous faisons, et cela fonctionne bien pour des milliers de requêtes pendant de nombreuses années, est simplement d'utiliser un alias pour Id, et de ne jamais spécifier de spliton (en utilisant le «Id» par défaut de Dapper).

select 
p.*,

c.CustomerID AS Id,
c.*

... voila! Dapper se divisera uniquement sur Id par défaut, et cet ID se produit avant toutes les colonnes du Client. Bien sûr, cela ajoutera une colonne supplémentaire à votre jeu de résultats de retour, mais cela représente une charge extrêmement minime pour l'utilitaire supplémentaire de savoir exactement quelles colonnes appartiennent à quel objet. Et vous pouvez facilement développer cela. Besoin d'adresse et d'informations sur le pays?

select
p.*,

c.CustomerID AS Id,
c.*,

address.AddressID AS Id,
address.*,

country.CountryID AS Id,
country.*

Mieux encore, vous montrez clairement une quantité minimale de SQL, dont les colonnes sont associées à quel objet. Dapper fait le reste.




Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi