天天看點

EntityFramework Core Raw Query再叙注意事項

前言

最近一直比較忙沒有太多時間去更新部落格,接下來會一直持續發表相關内容部落格,上一篇我們講到了EF Core中的原始查詢,這節我們再來叙述一下原始查詢,本文是基于在項目當中用到時發現的問題。

話題

我們通過EF Core原始查詢主要是用于一些需要連接配接多個表進行複雜查詢,下面我們來回顧下。我們定義一個ViewModel。

public class BlogViewModel
    {
        public string Name { get; set; }
        public string Url { get; set; }
        public string Title { get; set; }
        public string Content { get; set; }

    }      

我們将表Blog和Post表進行連接配接查詢出兩個表中的列,定義如下接口。

BlogViewModel GetBlog(int BlogId);      

接下來我們來寫SQL語句。

private EFCoreContext _efCoreContext;
        public BlogRepository(EFCoreContext efCoreContext) : base(efCoreContext)
        {
            _efCoreContext = efCoreContext;
        }

        public BlogViewModel GetBlog(int BlogId)
        {
            var sql = @"SELECT Name, Url, Content, Title
FROM dbo.Blog
    INNER JOIN dbo.Post ON dbo.Post.BlogId = dbo.Blog.Id
WHERE dbo.Blog.Id = {0}";
            var blogSingle = _efCoreContext.Set<BlogViewModel>().FromSql(sql, BlogId);
            return blogSingle.ToList().FirstOrDefault();
        }      

然後我們在控制器中進行查詢。

public IActionResult Index()
        {
            var blog = _blogRepository.GetBlog(2);
            return Ok();
        }      
EntityFramework Core Raw Query再叙注意事項

此時會出現如下錯誤:

Cannot create a DbSet for 'BlogViewModel' because this type is not included in the model for the context.      

我們知道當我們利用原始查詢出來的實體非EF Entity,而是由我們自定義的ViewModel。是以才會出現BlogViewModel未在EF上下文中,是以為了解決上述問題我們需要在EF上下文中定義ViewModel,如下:

public class EFCoreContext : DbContext
    {
        public EFCoreContext(DbContextOptions options) : base(options) { }

        public DbSet<BlogViewModel> BlogViewModels { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.AddEntityConfigurationsFromAssembly(GetType().GetTypeInfo().Assembly);
        }
    }      

然後我們在利用SQL查詢時需要用到上述BlogViewModels。如下:

public BlogViewModel GetBlog(int BlogId)
        {
            var sql = @"SELECT Name, Url, Content, Title
FROM dbo.Blog
    INNER JOIN dbo.Post ON dbo.Post.BlogId = dbo.Blog.Id
WHERE dbo.Blog.Id = {0}";
            var blogSingle = _efCoreContext.BlogViewModels.FromSql(sql, BlogId);
            return blogSingle.ToList().FirstOrDefault();
        }      

我們再來看看運作結果,結果依然出錯,錯誤顯示如下:

其他資訊: The entity type 'BlogViewModel' requires a primary key to be defined.      

根據提示我們再将BlogViewModel添加一個主鍵。

public class BlogViewModel
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Url { get; set; }
        public string Title { get; set; }
        public string Content { get; set; }

    }      

當然此時我們在寫SQL時也要傳回主鍵Id。

var sql = @"SELECT b.Id, b.Name, b.Url, p.Content, p.Title
FROM dbo.Blog AS b
    INNER JOIN dbo.Post AS p ON p.BlogId = b.Id
WHERE b.Id = {0}";      

此時我們再來運作看看。

EntityFramework Core Raw Query再叙注意事項

總結

本節我們探讨了EF Core中進行原始查詢需要注意的地方,我們再來做一個總結,當我們利用EF Core傳回一個ViewModel的話,此時我們需要将ViewModel定義在上文中,同時在ViewModel中需要定義一個主鍵,否則會出錯。好了,今天到此結束,我們下一篇會講講EF Core中的并發以及如何解決并發問題,多說一句,個人公衆号一直在更新和同步中,後續有可能一些比較簡短的内容會隻在公衆号上更新,為了讓使用者查閱公衆号内容更加便捷也在探索公衆号中,希望大家多多關注。 

你所看到的并非事物本身,而是經過诠釋後所賦予的意義