Entity Framework Core: AutoMapper로 쿼리 간소화
20863 단어 dotnetentityframeworkautomapper
public class Blog
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Post> Posts { get; set; }
}
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public Blog Blog { get; set; }
public List<Comment> Comments { get; set; }
}
public class Comment
{
public int Id { get; set; }
public string Content { get; set; }
public Post Post { get; set; }
}
그리고 DTO:
public class PostDto
{
public int Id { get; set; }
public string Title { get; set; }
public int BlogId { get; set; }
public string BlogName { get; set; }
public List<CommentDto> CommentsDto { get; set; }
}
public class CommentDto
{
public int Id { get; set; }
public string Content { get; set; }
}
public class PostSummaryDto
{
public int Id { get; set; }
public string Title { get; set; }
public int CommentsCount { get; set; }
}
Entity Framework로 데이터를 쿼리할 때 Include 메서드를 사용하는 것이 매우 일반적입니다. 그러나 여기에는 두 가지 단점이 있을 수 있습니다. 아마도 필요하지 않은 필드를 쿼리하게 될 것이고 두 번째는 엔터티를 다른 모델이나 DTO에 매핑해야 할 수도 있습니다.
var posts = await dbContext.Posts
.Include(x => x.Blog)
.Include(x => x.Comments)
.ToListAsync();
// map to DTO
이 쿼리의 경우 Entity Framework는 다음 SQL 코드를 생성합니다.
SELECT [p].[Id], [p].[BlogId], [p].[Title], [b].[Id], [b].[Name],
[c].[Id], [c].[Content], [c].[PostId]
FROM [Posts] AS [p]
INNER JOIN [Blogs] AS [b] ON [p].[BlogId] = [b].[Id]
LEFT JOIN [Comments] AS [c] ON [p].[Id] = [c].[PostId]
ORDER BY [p].[Id], [b].[Id]
이를 해결하는 기존 방법은 프로젝션을 사용하여 필요한 필드를 선택하고 엔터티 대신 DTO를 직접 사용하는 것입니다.
var post = await dbContext.Posts
.Select(x => new PostDto()
{
Id = x.Id,
Title = x.Title,
BlogId = x.Blog.Id,
BlogName = x.Blog.Name,
CommentsDto = x.Comments.Select(c => new CommentDto()
{
Id = c.Id,
}).ToList()
})
.ToListAsync();
결과는 다음과 같습니다.
SELECT [p].[Id], [p].[Title], [b].[Id], [b].[Name], [c].[Id]
FROM [Posts] AS [p]
INNER JOIN [Blogs] AS [b] ON [p].[BlogId] = [b].[Id]
LEFT JOIN [Comments] AS [c] ON [p].[Id] = [c].[PostId]
ORDER BY [p].[Id], [b].[Id]
그러나 수동으로 쿼리를 작성하는 것은 약간 지루할 수 있습니다.
구조에 ProjectTO
AutoMapper에는
.ProjectTo
방법을 사용하여 이 문제를 해결하는 간단한 방법이 있습니다.var posts = await mapper.ProjectTo<PostDto>(dbContext.Posts, null).ToListAsync();
프로젝션과 정확히 동일한 쿼리 생성:
SELECT [p].[Id], [p].[Title], [b].[Id], [b].[Name], [c].[Id]
FROM [Posts] AS [p]
INNER JOIN [Blogs] AS [b] ON [p].[BlogId] = [b].[Id]
LEFT JOIN [Comments] AS [c] ON [p].[Id] = [c].[PostId]
ORDER BY [p].[Id], [b].[Id]
.ProjectTo<PostDto>()
는 DTO에 있는 필드만 쿼리하면 됨을 Entity Framework에 알리는 IQueryable에 대한 select 절을 내보내도록 AutoMapper의 매핑 엔진에 지시합니다..ProjectTo
의 일반적인 경우는 작은 DTO/모델을 사용하는 것입니다. 예를 들어 더 작은 DTO를 사용하여 프런트엔드에 나열할 게시물 요약을 ID, 이름 및 댓글 수와 함께 반환할 수 있습니다.public class PostSummaryDto
{
public int Id { get; set; }
public string Title { get; set; }
public int CommentsCount { get; set; }
}
그리고 C#에서 단 한 줄만 다시 작성합니다.
var postSummary = await mapper.ProjectTo<PostSummaryDto>(dbContext.Posts, null).ToListAsync();
SQL 코드는 정말 멋져 보입니다.
SELECT [p].[Id], [p].[Title], (
SELECT COUNT(*)
FROM [Comments] AS [c]
WHERE [p].[Id] = [c].[PostId]
) AS [CommentsCount]
FROM [Posts] AS [p]
보시다시피 코드 한 줄만 사용하여 매우 성능이 좋은 쿼리를 만들 수 있습니다.
.ProjectTo
에 대한 자세한 내용을 보려면 here을 읽으십시오.
Reference
이 문제에 관하여(Entity Framework Core: AutoMapper로 쿼리 간소화), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/cloudx/entity-framework-core-simplify-your-queries-with-automapper-3m8k텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)