Comportement inattendu avec une requête multi-mapping utilisant Dapper.net

asp.net c# dapper mapping

Question

Je viens juste de commencer à regarder Dapper.net et je viens d’expérimenter différentes requêtes, dont l’une produit des résultats étranges auxquels je ne m'attendais pas.

J'ai 2 tableaux - Photos & PhotoCategories , dont sont liés à CategoryID

Tableau de photos

PhotoId (PK - int)  
CategoryId (FK - smallint)  
UserId (int)

Table PhotoCategories

CategoryId (PK - smallint)  
CategoryName (nvarchar(50))

Mes 2 cours:

public class Photo
{
    public int PhotoId { get; set; }
    public short CategoryId { get; set; }
    public int UserId { get; set; }
    public PhotoCategory PhotoCategory { get; set; }
}

public class PhotoCategory
{
    public short CategoryId { get; set; }
    public string CategoryName { get; set; }
{

Je souhaite utiliser le multi-mapping pour renvoyer une instance de Photo , avec une instance remplie de PhotoCategory associée.

var sql = @"select p.*, c.* from Photos p inner 
            join PhotoCategories c 
            on p.CategoryID = c.CategoryID where p.PhotoID = @pid";

cn.Open();
var myPhoto = cn.Query<Photo, PhotoCategory, Photo>(sql, 
               (photo, photoCategory) => { photo.PhotoCategory = photoCategory; 
                                           return photo; }, 
               new { pid = photoID }, null, true, splitOn: "CategoryID").Single();

Lorsque ceci est exécuté, toutes les propriétés ne sont pas remplies (malgré les mêmes noms entre la table de base de données et dans mes objets.

J'ai remarqué que si je don't sélectionne pas p. dans mon SQL , et à la place.

Je déclare explicitement les champs.

Je veux revenir EXCLUDING p.CategoryId de la requête, alors tout est peuplé (sauf évidemment le CategoryId contre l'objet Photo que j'ai exclu de l'instruction select).

Mais je m'attendrais à être en mesure d'inclure ce champ dans la requête, et de l'avoir, ainsi que tous les autres champs interrogés dans le SQL , à être rempli.

Je pourrais simplement exclure la propriété CategoryId de ma classe Photo et utiliser toujours Photo.PhotoCategory.CategoryId lorsque j'ai besoin de l'ID.

Mais dans certains cas, je ne souhaite peut-être pas remplir l'objet PhotoCategory lorsque j'obtiens une instance de l'objet Photo.

Est-ce que quelqu'un sait pourquoi le comportement ci-dessus se produit? Est-ce normal pour Dapper?

Réponse acceptée

Je viens de commettre un correctif pour cela:

    class Foo1 
    {
        public int Id;
        public int BarId { get; set; }
    }

    class Bar1
    {
        public int BarId;
        public string Name { get; set; }
    }

    public void TestMultiMapperIsNotConfusedWithUnorderedCols()
    {

        var result = connection.Query<Foo1,Bar1,
                      Tuple<Foo1,Bar1>>(
                         "select 1 as Id, 2 as BarId, 3 as BarId, 'a' as Name",
                         (f,b) => Tuple.Create(f,b), splitOn: "BarId")
                         .First();

        result.Item1.Id.IsEqualTo(1);
        result.Item1.BarId.IsEqualTo(2);
        result.Item2.BarId.IsEqualTo(3);
        result.Item2.Name.IsEqualTo("a");

    }

Le multi-mappeur devenait confus s'il y avait un champ dans le first type, qui se trouvait également dans le second type ... ET ... était utilisé comme point de partage.

Pour vaincre maintenant, dapper permet au champ Id de s'afficher n'importe où dans le premier type. Pour illustrer.

Disons que nous avons:

classes: A{Id,FooId} B{FooId,Name}
splitOn: "FooId"
data: Id, FooId, FooId, Name

L'ancienne méthode de fractionnement ne tenait aucun compte du type sous-jacent réel qu'elle mappait. Donc ... il a mappé Id => A et FooId, FooId, Name => B

La nouvelle méthode prend en compte les accessoires et les champs dans A Quand il rencontre FooId pour la première fois dans le flux, il ne lance pas de division, sachant que A possède une propriété appelée FooId qui doit être mappée, la prochaine fois qu'il verra FooId il se divisera, ce qui entraînera les résultats attendus.


Réponse populaire

Je sais que cette question est ancienne mais je pensais sauver 2 minutes à quelqu'un avec la réponse évidente à ceci: alias juste un identifiant d'une table:

c'est à dire:

SELECT
    user.Name, user.Email, user.AddressId As id, address.*
FROM 
    User user
    Join Address address
    ON user.AddressId = address.AddressId



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