如何使用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;
我知道我真的迟到了,但还有另一种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();