web-dev-qa-db-fra.com

Lorsque vous utilisez les API de mappage multiple, assurez-vous de définir le paramètre splitOn si vous avez des clés autres que l'ID "," splitOn

J'essaie d'utiliser la fonction de multi-mappage de dapper pour renvoyer une liste d'albums et d'artistes et de genres associés.

public class Artist
{
public virtual int ArtistId { get; set; }
public virtual string Name { get; set; }
}    


public class Genre
{
public virtual int GenreId { get; set; }
public virtual string Name { get; set; }
public virtual string Description { get; set; }
}


public class Album
{
public virtual int AlbumId { get; set; }
public virtual int GenreId { get; set; }
public virtual int ArtistId { get; set; }
public virtual string Title { get; set; }
public virtual decimal Price { get; set; }
public virtual string AlbumArtUrl { get; set; }
public virtual Genre Genre { get; set; }
public virtual Artist Artist { get; set; }
}


var query = @"SELECT AL.Title, AL.Price, AL.AlbumArtUrl, GE.Name, GE.[Description], AR.Name FROM Album AL INNER JOIN Genre GE ON AL.GenreId = GE.GenreId INNER JOIN Artist AR ON AL.ArtistId = AL.ArtistId";

var res = connection.Query<Album, Genre, Artist, Album>(query, (album, genre, artist) => { album.Genre = genre; album.Artist = artist; return album; }, commandType: CommandType.Text, splitOn: "ArtistId, GenreId");

J'ai vérifié la solution à ce sujet, cela n'a pas fonctionné. Quelqu'un peut-il me dire où je me suis trompé?

Merci @Alex :) Mais je suis toujours frappé. Voici ce que j'ai fait:

CREATE TABLE Artist
(
ArtistId INT PRIMARY KEY IDENTITY(1,1)
,Name VARCHAR(50)
)

CREATE TABLE Genre
(
    GenreId INT PRIMARY KEY IDENTITY(1,1)
    ,Name VARCHAR(20)
    ,[Description] VARCHAR(1000)
)

CREATE TABLE Album
(
    AlbumId INT PRIMARY KEY IDENTITY(1,1)
    ,GenreId INT FOREIGN KEY REFERENCES Genre(GenreId)
    ,ArtistId INT FOREIGN KEY REFERENCES Artist(ArtistId)
    ,Title VARCHAR(100)
    ,Price FLOAT
    ,AlbumArtUrl VARCHAR(300) 
)

INSERT INTO Artist(Name) VALUES ('Jayant')
INSERT INTO Genre(Name,[Description]) VALUES ('Rock','Originally created during school days. The year was.....I guess 1998')
DECLARE @gen_id INT
        ,@art_id INT
SET @gen_id = (SELECT MAX(GenreId) FROM Genre)
SET @art_id = (SELECT MAX(ArtistId) FROM Artist)
INSERT INTO Album(GenreId,ArtistId,Title,Price,AlbumArtUrl) VALUES (@gen_id,@art_id,'I go mad for you',200,'http://asha4u.com/IGoMad')

Comme vous l'avez suggéré, j'ai modifié la requête en:

var query = @"SELECT AL.AlbumId, AL.Title, AL.Price, AL.AlbumArtUrl, GE.GenreId, GE.Name, GE.Description, AR.ArtistId, AR.Name FROM Album AL INNER JOIN Artist AR ON AR.ArtistId = AL.ArtistId INNER JOIN Genre GE ON GE.GenreId = AL.GenreId";

var res = connection.Query<Album, Genre, Artist, Album>(query, (album, genre, artist) => { album.Genre = genre; album.Artist = artist; return album; }, commandType: CommandType.Text, splitOn: "GenreId, ArtistId");

Maintenant, j'utilise splitOn pour GenreId et ArtistId. Je reçois toujours la même erreur. Veuillez aider.

28
user2497013

Vous devez inclure la colonne que vous souhaitez fractionner dans votre requête de sélection. La vôtre sélectionne simplement toutes les autres propriétés - donc Dapper ne trouve pas de colonne correspondante pour diviser les objets.

Votre requête devrait probablement être quelque chose comme ça:

var query = @"SELECT AlbumId, Title, Price, AlbumArtUrl, GenreId, Name, Description , ArtistId, Name ......" etc

Sam a écrit une excellente réponse pour les mappages multiples et l'option splitOn: https://stackoverflow.com/a/7478958/102832

Modifier: si votre requête est comme mentionné ci-dessus, vous devrez diviser sur GenreId et ArtistId.

 AlbumId, Title, Price, AlbumArtUrl | GenreId, Name, Description | ArtistId, Name

Les tuyaux sont pour le début d'un nouveau POCO que vous essayez de cartographier. Les paramètres SplitOn seraient donc GenreId et ArtistId.

Edit2: Le problème est votre POCO Album. Vous spécifiez ArtistId et GenreId comme propriétés mais elles appartiennent essentiellement à leurs POCO's.

public class Album
    {
        public virtual int AlbumId { get; set; }
        public virtual string Title { get; set; }
        public virtual decimal Price { get; set; }
        public virtual string AlbumArtUrl { get; set; }
        public virtual Genre Genre { get; set; }
        public virtual Artist Artist { get; set; }
    }

et

var sql = @"SELECT AL.AlbumId
                 , AL.Title
                 , AL.Price
                 , AL.AlbumArtUrl
                 , GE.GenreId
                 , GE.Name
                 , GE.Description
                 , AR.ArtistId
                 , AR.Name 
            FROM Album AL 
      INNER JOIN Artist AR ON AR.ArtistId = AL.ArtistId 
      INNER JOIN Genre GE ON GE.GenreId = AL.GenreId";

using (var conn = connFactory.OpenConnection())
{
    var res = conn.Query<Album, Genre, Artist, Album>(sql, (album, genre, artist) =>
    {
        album.Genre = genre;
        album.Artist = artist;
        return album;
    }, splitOn: "GenreId,ArtistId");
}

devrait faire l'affaire. De toute façon, vous n'avez pas besoin de GenreId et ArtistId car vous avez une référence à ces objets dans Albums.

41
Alex