C# 使用多重映射API时,如果您有Id以外的键,请确保设置splitOn参数&引用;斯普利顿

C# 使用多重映射API时,如果您有Id以外的键,请确保设置splitOn参数&引用;斯普利顿,c#,dapper,C#,Dapper,我正在尝试使用dapper的多重映射功能来返回专辑列表以及相关的艺术家和流派 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; se

我正在尝试使用dapper的多重映射功能来返回专辑列表以及相关的艺术家和流派

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");
根据您的建议,我将查询更改为:

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");
var query=@“从相册中选择AL.AlbumId、AL.Title、AL.Price、AL.AlbumArtUrl、GE.GenreId、GE.Name、GE.Description、AR.ArtistId、AR.Name AL-in-JOIN-Artist-AR-ON-AR.ArtistId=AL.ArtistId-in-GenreId=AL.GenreId”;
var res=connection.Query(查询,(唱片集,流派,艺术家)=>{album.genre=genre;唱片集.艺术家=艺术家;返回唱片集;},commandType:commandType.Text,splitOn:“GenreId,ArtistId”);

现在我正在为GenreId和ArtistId使用splitOn。我仍然会犯同样的错误。请提供帮助。

您需要在select查询中包含要拆分的列。您的属性只是选择所有其他属性,因此
Dapper
没有找到匹配的列来分割对象

您的查询可能如下所示:

var query = @"SELECT AlbumId, Title, Price, AlbumArtUrl, GenreId, Name, Description , ArtistId, Name ......" etc
Sam为多重映射和splitOn选项写了一个极好的答案:

编辑:如果您的查询如上所述,则必须在GenreId和ArtistId上进行拆分

 AlbumId, Title, Price, AlbumArtUrl | GenreId, Name, Description | ArtistId, Name
这些管道是用于您尝试映射的新POCO的开始。因此,
SplitOn
参数将是GenreId和ArtistId

Edit2:问题是你的POCO
相册
。您可以指定
ArtistId
GenreId
作为属性,但它们基本上属于各自的
POCO

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

var sql=@“选择AL.AlbumId
,AL.Title
,艾尔·普莱斯
,AL.AlbumArtUrl
,GE.GenreId
,GE.Name
,GE.说明
,AR.ArtistId
,AR.名称
来自专辑AL
内部连接艺术家AR ON AR.ArtistId=AL.ArtistId
内部连接类型GE ON GE.GenreId=AL.GenreId”;
使用(var conn=connFactory.OpenConnection())
{
var res=conn.Query(sql,(专辑、流派、艺术家)=>
{
专辑风格=风格;
专辑。艺术家=艺术家;
返回相册;
},斯普利顿:“根里德,艺术家”);
}
我们应该做到这一点。无论如何,您不需要
GenreId
ArtistId
,因为您在
相册中引用了这些对象

我也遇到了同样的问题。 这里是技巧和例子

public abstract class BaseEntity
{
    [Key]
    public int Id { get; set; }
}

public class Category : BaseEntity
{
    public string Name { get; set; }
}


public class Status : BaseEntity
{
    public string Name { get; set; }
}

public class User : BaseEntity
{
    public string Name { get; set; }
    public string Surname { get; set; }
    public bool Active { get; set; }
}


public class TodoItem : BaseEntity
{
    public string Title { get; set; }
    public string Message { get; set; }
    public Status Status { get; set; }
    public Category Category { get; set; }
    public User User { get; set; }
    public DateTime CreatedOn { get; set; }
}
使用

            string sql = @"select 
                          t.Id,
                          t.Title,
                          t.Message,
                          t.CreatedOn,
                          s.Id as Id,
                          s.Name,

                          c.Id as Id,
                          c.Name,

                          u.Id as Id,
                          u.Name,
                          u.Surname,
                          u.Active

                         from ToDoItem t
                        inner join [Status] s on (t.StatusId = s.Id)
                        inner join [Category] c on (t.CategoryId = c.Id)
                        inner join [User] u on (t.AssignUserId = u.Id)";
            var result = connection.Query<TodoItem, Status, Category, User, TodoItem>
                (sql, (todoItem, status, category, user) =>
            {
                todoItem.Status = status;
                todoItem.Category = category;
                todoItem.User = user;
                return todoItem;
            },splitOn: "Id,Id,Id,Id");
stringsql=@“选择
t、 身份证,
t、 头衔,
t、 信息,
t、 CreatedOn,
s、 Id作为Id,
s、 名字,
c、 Id作为Id,
c、 名字,
u、 Id作为Id,
u、 名字,
u、 姓,
u、 活跃的
从今
内部联接[Status]s打开(t.StatusId=s.Id)
内部联接[Category]c on(t.CategoryId=c.Id)
内部连接[User]u on(t.AssignUserId=u.Id)”;
var result=connection.Query
(sql,(todoItem、状态、类别、用户)=>
{
todoItem.Status=状态;
todoItem.Category=类别;
todoItem.User=用户;
返回doitem;
},splitOn:“Id,Id,Id,Id”);

这里有一个技巧拆分:“Id,Id,Id,Id”

在做出您建议的更改后,它仍然不起作用。我更改了查询,只考虑了艺术家和专辑类。query=“选择AR.ArtistId、AR.Name、AL.AlbumId、AL.Price、AL.Title、AL.AlbumArtUrl从艺术家AR内部加入AR.ArtistId=AL.AlbumId上的Album AL”;var item=connection.Query(Query,(album,artist)=>{album.artist=artist;return album;},commandType:commandType.Text,splitOn:“ArtistId”);它仍然没有work@user2497013请参阅我的编辑。最简单的方法是形成SQL,使其与您试图以正确顺序匹配的POCO相匹配。目前,您正在使用ArtistId进行拆分-这告诉Dapper尝试将ArtistId之后的所有属性映射到一个不正确的POCO。我更改了查询,但仍然无法工作。var query=@“从相册中选择AL.AlbumId、AL.Title、AL.Price、AL.AlbumArtUrl、GE.GenreId、GE.Name、GE.Description、AR.ArtistId、AR.Name 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=genre;唱片集.艺术家=艺术家;返回唱片集;},commandType:commandType.Text,splitOn:“GenreId,ArtistId”);请帮忙。问题在于你的POCO。您需要从相册中删除GenreId和ArtistId,否则Dapper将以未定义的行为结束:)非常感谢您的努力。。最后代码成功了:)将ArtistId和GenreId从POCO专辑中删除就成功了。干杯
public abstract class BaseEntity
{
    [Key]
    public int Id { get; set; }
}

public class Category : BaseEntity
{
    public string Name { get; set; }
}


public class Status : BaseEntity
{
    public string Name { get; set; }
}

public class User : BaseEntity
{
    public string Name { get; set; }
    public string Surname { get; set; }
    public bool Active { get; set; }
}


public class TodoItem : BaseEntity
{
    public string Title { get; set; }
    public string Message { get; set; }
    public Status Status { get; set; }
    public Category Category { get; set; }
    public User User { get; set; }
    public DateTime CreatedOn { get; set; }
}
            string sql = @"select 
                          t.Id,
                          t.Title,
                          t.Message,
                          t.CreatedOn,
                          s.Id as Id,
                          s.Name,

                          c.Id as Id,
                          c.Name,

                          u.Id as Id,
                          u.Name,
                          u.Surname,
                          u.Active

                         from ToDoItem t
                        inner join [Status] s on (t.StatusId = s.Id)
                        inner join [Category] c on (t.CategoryId = c.Id)
                        inner join [User] u on (t.AssignUserId = u.Id)";
            var result = connection.Query<TodoItem, Status, Category, User, TodoItem>
                (sql, (todoItem, status, category, user) =>
            {
                todoItem.Status = status;
                todoItem.Category = category;
                todoItem.User = user;
                return todoItem;
            },splitOn: "Id,Id,Id,Id");