I have this simple Blog database structure with 4 tables:
and some sample data in each table looks like this:
Blogs table:
Posts table:
Tags table:
PostTags table:
And I have this SQL script.
SELECT b.Id,
b.Title,
p.Id,
p.Title,
p.PostContent,
t.Name
FROM dbo.Blogs b
JOIN Posts p ON p.BlogId = b.Id
LEFT JOIN PostTags pt ON pt.PostId = p.Id
LEFT JOIN Tags t ON t.Id = pt.TagId
WHERE b.Id = 1
AND p.IsDeleted = 0;
There are a few ways to execute this script with EF Core. One is to call this SQL script directly from the code. Another way to create a stored procedure or view and call that from the code.
Supposed I have the followings classes to map the result of executed SQL script by EF Core.
public partial class Blog
{
public int Id { get; set; }
public string Title { get; set; }
public string Slogan { get; set; }
public virtual ICollection<Post> Posts { get; set; }
}
public partial class Post
{
public int Id { get; set; }
public int BlogId { get; set; }
public string Title { get; set; }
public string PostContent { get; set; }
public virtual ICollection<PostTag> PostTags { get; set; }
}
public partial class Tag
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<PostTag> PostTags { get; set; }
}
public partial class PostTag
{
public int Id { get; set; }
public int PostId { get; set; }
public int TagId { get; set; }
public virtual Post Post { get; set; }
public virtual Tag Tag { get; set; }
}
This is a method in a controller:
[Route("posts/{blogId}")]
[HttpGet]
public async Task<IActionResult> GetBlogPosts(int blogId)
{
string sql = @"
SELECT b.Id,
b.Title,
p.Id,
p.Title,
p.PostContent,
t.Id,
t.Name
FROM dbo.Blogs b
JOIN Posts p ON p.BlogId = b.Id
LEFT JOIN PostTags pt ON pt.PostId = p.Id
LEFT JOIN Tags t ON t.Id = pt.TagId
WHERE b.Id = 1
AND p.IsDeleted = 0;
";
// this is not working
var result = db.Blogs.FromSql(sql).ToList().FirstOrDefault();
return Ok(result);
}
How I can map the result of the SQL script to the Blog
object so that I can have the following result?
{
"Blog": [
{
"Id": 1,
"Title": "Another .NET Core Guy",
"Posts": [
{
"Id": 1,
"Title": "Post 1",
"PostContent": "Content 1 is about EF Core and Razor page",
"Tags": [
{
"Id": 1,
"Name": "Razor Page"
},
{
"Id": 2,
"Name": "EF Core"
}
]
},
{
"Id": 2,
"Title": "Post 2",
"PostContent": "Content 2 is about Dapper",
"Tags": [
{
"Id": 3,
"Name": "Dapper"
}
]
},
{
"Id": 4,
"Title": "Post 4",
"PostContent": "Content 4",
"Tags": [
{
"Id": 5,
"Name": "SqlKata"
}
]
}
]
}
]
}
Update August 13, 2019:
EF Core does not support this kind of feature yet as it has been stated here on EF Core Github page https://github.com/aspnet/EntityFrameworkCore/issues/14525