Dapper로 중첩 된 개체 목록을 매핑하는 방법
현재 DB 액세스를 위해 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()}
);
모든 것을 매핑
독자에게 맡기고 몇 개의 맵을 만들고 작성하는 과정을 반복합니다.
주의in
미만의 경우 트릭이 작동합니다 (2100) 조회 (SQL 서버)이있는 경우, 당신은 아마 더에 쿼리를 수정하려면 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/
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) => {
course.Locations = course.Locations ?? new List<Location>();
course.Locations.Add(location);
return course;
}).AsQueryable();
나는 이것에 가족을 늦었다는 것을 선택하는 옵션이 있습니다. 여기에서 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();
}
잘가 빠졌어. Locations
SQL 쿼리에서 각 필드를 지정하지 않는 개체 개체가 Location
채울 수 없습니다. 구경하다 :
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.*
쿼리에서 위치 목록이 데이터는 없습니다.
파티에 늦어서 미안합니다 (언제나 그렇듯이). 나를 위해, 그것은 사용하는 것이 더 나은 것이 Dictionary
, 제론 K했던 것처럼 성능과 가독성의 건물에서. 또한 위치 간 헤더가 곱셈을 위해 외장 Distinct()
을 제거 하는 데 사용 합니다.
string query = @"SELECT c.*, l.*
FROM Course c
INNER JOIN Location l ON c.LocationId = l.Id";
using (SqlConnection conn = DB.getConnection())
{
conn.Open();
var courseDictionary = new Dictionary<Guid, Course>();
var list = conn.Query<Course, Location, Course>(
query,
(course, location) =>
{
if (!courseDictionary.TryGetValue(course.Id, out Course courseEntry))
{
courseEntry = course;
courseEntry.Locations = courseEntry.Locations ?? new List<Location>();
courseDictionary.Add(courseEntry.Id, courseEntry);
}
courseEntry.Locations.Add(location);
return courseEntry;
},
splitOn: "Id")
.Distinct()
.ToList();
return list;
}
누구에게 필요한지 확실하지 않지만 유연한 코딩을 위해 Model없이 동적 버전이 있습니다.
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;
참고 URL : https://stackoverflow.com/questions/7508322/how-do-i-map-lists-of-nested-objects-with-dapper
'IT' 카테고리의 다른 글
안드로이드 레이아웃 :이 태그와 그 하나는 대체 될 수 있습니다. (0) | 2020.08.07 |
---|---|
C #에서 메모장으로 파일 열기 (0) | 2020.08.07 |
프로그래밍 방식으로 자바 펼쳐 함수에 코드 추가 (0) | 2020.08.07 |
버전 관리를 위해 태그와 릴리스 / 베타 관리를위한 이유는 무엇입니까? (0) | 2020.08.07 |
Rails : 두 열의 고유성 확인 (함께) (0) | 2020.08.07 |