我有一个Place对象。
它可以有许多与之关联的标签。
标签可以与多个地方相关联。
(虽然这是一个多对多的关系 - 我想在概念上它也可能是一对多 - 一组对象 - 每个对象都包含一组对象。)
每个Place对象都有一个与之关联的List集合:
public class Place
{
public Guid Id { get; set; }
public string PlaceName { get; set; }
...
public List<Tag> Tags { get; set; }
}
public class Tag
{
public Guid Id { get; set; }
public string TagName { get; set; }
}
从多对多关系中选择所需数据的SQL:
select * from place p
inner join tagplace tp on tp.placeid = p.id
inner join tag t on t.id = tp.tagid
order by placename
我可以在一个Dapper命令中映射所有这些(或者至少不是n + 1个命令)吗? Github文档涵盖了一对多的关系 - 但不是很多。
(我需要这样做的原因 - 是因为我想输出所有地方的网格,我希望一列是逗号分隔的标签列表(我将创建一个带有标签集合的Helper)输出以逗号分隔的字符串)。
我看到了一个类似的问题,建议使用Slapper.AutoMapper:
How do I write one to many query in Dapper.Net?
如果可能的话,我宁愿避免使用额外的库 - 但我想这里可能需要它?
最好的办法是什么?
答案 0 :(得分:1)
我想输出所有地方的网格,我希望一列成为一个 逗号分隔的标签列表
由于你想要所有的地方,你需要使用LEFT JOIN而不是内连接来获取所有的地方及其相关的标签。
var query = @"select p.Id,p.Name,t.TagName from place p
leftjoin tagplace tp on tp.placeid = p.id
left join tag t on t.id = tp.tagid
order by placename";
此查询将为结果集提供3列:Id,Name和TagName。我会为结果集记录创建一个简单的DTO。
internal class PlaceTagDto
{
public Guid Id { internal set;get;}
public string Name { internal set;get;}
public string TagName { internal set; get }
}
现在使用Dapper执行查询并将结果映射到PostTagDto集合。然后按TagName对结果进行分组。
using(var c=new SqlConnecction("YourConnectionString"))
{
var r=cn.Query<PlaceTagDto>(query);
var grouped=r.GroupBy(s => s.Id, i => i,
(k, groupdPlaces) => new Place {
Id = k,
PlaceName = groupdPlaces.First().Name,
Tags = groupdPlaces.Where(y=>y.TagID!=null)
.Select(t=>new Tag
{
TagName = t.TagName
}).ToList()
});
}
此外,如果您将Tags属性类型从List<Tag>
更改为IEnumerable<Tag>
,则可以避免LINQ表达式中的ToList()
调用。
现在,在您的用户界面中,您可以使用String.Join
方法显示以逗号分隔的标记列表,
@model IEnumerable<Place>
<table>
@foreach(var p in Model)
{
<tr>
<td>@p.Name</td>
<td>
@String.Join(",",p.Tags.Select(s=>s.TagName))
</td>
</tr>
}
</table>