如何使用Dapper映射嵌套对象的列表

我目前正在使用entity framework来访问我的数据库,但想看看Dapper。 我有这样的课程:

public class Course{ public string Title{get;set;} public IList<Location> Locations {get;set;} ... } public class Location{ public string Name {get;set;} ... } 

所以一个课程可以在几个地方教授。 entity framework为我做了映射,所以我的课程对象填充了位置列表。 我将如何与Dapper一起讨论这个问题,甚至有可能,还是需要在几个查询步骤中完成?

谢谢。

Dapper不是一个完整的ORM,它不能处理查询等的魔法生成。

对于您的特定示例,以下内容可能会起作用:

抓住课程:

 var courses = cnn.Query<Course>("select * from Courses where Category = 1 Order by CreationDate"); 

抓住相关的映射:

 var mappings = cnn.Query<CourseLocation>( "select * from CourseLocations where CourseId in @Ids", new {Ids = courses.Select(c => c.Id).Distinct()}); 

抓住相关的地点

 var locations = cnn.Query<Location>( "select * from Locations where Id in @Ids", new {Ids = mappings.Select(m => m.LocationId).Distinct()} ); 

映射一切

留给读者,你创build一些地图,并遍历你的课程与位置填充。

如果你的查询less于2100 (Sql Server),如果你有更多的你可能想要修改查询来select * from CourseLocations where CourseId in (select Id from Courses ... )如果您使用QueryMultiple ,则可以一次性将所有结果全部抽出

或者,您可以使用查询来查询一个查询:

 var lookup = new Dictionary<int, Course>(); conn.Query<Course, Location, Course>(@" SELECT c.*, l.* FROM Course c INNER JOIN Location l ON c.LocationId = l.Id ", (c, l) => { Course course; if (!lookup.TryGetValue(c.Id, out course)) { lookup.Add(c.Id, course = c); } if (course.Locations == null) course.Locations = new List<Location>(); course.Locations.Add(l); /* Add locations to course */ return course; }).AsQueryable(); var resultList = lookup.Values; 

看到这里https://www.tritac.com/blog/dappernet-by-example/

我知道我真的迟到了,但还有另一种select。 你可以在这里使用QueryMultiple。 像这样的东西:

 var results = cnn.QueryMultiple("select * from Courses where Category = 1 Order by CreationDate; select A.*, B.CourseId from Locations A Inner Join CourseLocations B on A.LocationId = B.LocationId Inner Join Course C On B.CourseId = B.CourseId And C.Category = 1"); var courses = results.Read<Course>(); var locations = results.Read<Location>(); //(Location will have that extra CourseId on it for the next part) foreach (var course in courses) { course.Locations = locations.Where(a => a.CourseId == course.CourseId).ToList(); } 

缺了点什么。 如果不在SQL查询中指定位置中的每个字段,则无法填充对象位置。 看一看:

 var lookup = new Dictionary<int, Course>() conn.Query<Course, Location, Course>(@" SELECT c.*, l.Name, l.otherField, l.secondField FROM Course c INNER JOIN Location l ON c.LocationId = l.Id ", (c, l) => { Course course; if (!lookup.TryGetValue(c.Id, out course)) { lookup.Add(c.Id, course = c); } if (course.Locations == null) course.Locations = new List<Location>(); course.Locations.Add(a); return course; }, ).AsQueryable(); var resultList = lookup.Values; 

在查询中使用“l。*”,我有位置列表但没有数据。

不知道是否有人需要它,但我没有快速和灵活的编码模型的dynamic版本。

  var lookup = new Dictionary<int, dynamic>(); conn.Query<dynamic, dynamic, dynamic>(@" SELECT A.*, B.* FROM Client A INNER JOIN Instance B ON A.ClientID = B.ClientID ", (A, B) => { // If dict has no key, allocate new obj // with another level of array if (!lookup.ContainsKey(A.ClientID)){ lookup[A.ClientID] = new { ClientID = A.ClientID, ClientName = A.Name, Instances = new List<dynamic>() }; } // Add each instance lookup[A.ClientID].Instances.Add(new { InstanceName = B.Name, BaseURL = B.BaseURL, WebAppPath = B.WebAppPath }); return lookup[A.ClientID]; }, splitOn: "ClientID,InstanceID").AsQueryable(); var resultList = lookup.Values; return resultList; 

不需要lookup字典

 var coursesWithLocations = conn.Query<Course, Location, Course>(@" SELECT c.*, l.* FROM Course c INNER JOIN Location l ON c.LocationId = l.Id ", (course, location) => { if (course.Locations == null) course.Locations = new List<Location>(); course.Locations.Add(location); return course; }).AsQueryable();