开发者社区> 问答> 正文

具有自定义返回类型的实体框架核心-无法为'BookInfo'创建DbSet,因为此类型未包含在上下文

具有自定义返回类型的实体框架核心

我正在尝试使用EF Core 3.1从Sql Server查询自定义返回类型。有两个实体Book和Author,我想获取具有BookId,BookName,AuthorName的BookInfo。这是下面的代码。

存储过程:

```js
CREATE PROC GetBookInfos
AS
SELECT Books.BookId, Books.Name AS BookName, Authors.FirstName+' '+Authors.LastName AS AuthorName
FROM Books
INNER JOIN Authors
ON Books.AuthorId = Authors.AuthorId;

Book.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace EFCoreShop
{
    public class Book
    {
        public long BookId { get; set; }
        public string Name { get; set; }
        public double Price { get; set; }
        public long AuthorId { get; set; }
        public Author Author { get; set; }
    }
}
作者.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace EFCoreShop
{
    public class Author
    {
        public long AuthorId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public List<Book> Books { get; set; }
    }
}

BookInfo.cs

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text;

namespace EFCoreShop
{
    [NotMapped]
    public class BookInfo
    {
        public long BookId { get; set; }
        public string BookName { get; set; }
        public string AuthorName { get; set; }
    }
}

ShopContext.cs

using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Text;

namespace EFCoreShop
{
    class ShopContext:DbContext
    {

        public DbSet<Author> Authors { get; set; }
        public DbSet<Book> Books { get; set; }
        public DbSet<BookInfo> BookInfos { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer("Data Source=**********;Database=EFCoreShop;User ID=*********;Password=***********");
        }


    }
}
Program.cs

using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;

namespace EFCoreShop
{
    class Program
    {
        static void Main(string[] args)
        {
            using (ShopContext shopContext = new ShopContext())
            {
                IEnumerable<BookInfo> bookInfos = shopContext.BookInfos.FromSqlRaw("exec GetBookInfos").ToList<BookInfo>();

                foreach (var bookInfo in bookInfos)
                {
                    Console.WriteLine($"Book Id: {bookInfo.BookId} Book Name: {bookInfo.BookName} Author Name: {bookInfo.AuthorName}");
                } 
            }
        }
    }
}

我想我做得很好。我正在尝试从数据库返回自定义类型,并且已经在其中存储了过程。我也不想映射实体。

注意:我知道我可以使用EF Core中的内部联接来做到这一点。但是,我试图从具有自定义返回类型的存储过程中获取数据。

您能指导我解决此问题吗?

错误:

Unhandled exception. System.InvalidOperationException: Cannot create a DbSet for 'BookInfo' because this type is not included in the model for the context.
   at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.get_EntityType()
   at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.CheckState()
   at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.get_EntityQueryable()
   at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.System.Linq.IQueryable.get_Provider()
   at Microsoft.EntityFrameworkCore.RelationalQueryableExtensions.FromSqlRaw[TEntity](DbSet`1 source, String sql, Object[] parameters)
   at EFCoreShop.Program.Main(String[] args) in D:\Workspace\Learning\DotNet\EFCoreShop\EFCoreShop\Program.cs:line 14

更新: 下面的代码无需使用存储过程即可解决该问题。但是,我们需要使用存储过程的结果。但是,如果您不想使用存储过程,也可以这样做。

Program.cs(没有存储过程,不是我想要的)

using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;

namespace EFCoreShop
{
    class Program
    {
        static void Main(string[] args)
        {
            using (ShopContext shopContext = new ShopContext())
            {
                //IEnumerable<BookInfo> bookInfos = shopContext.BookInfos.FromSqlRaw("exec GetBookInfos").ToList<BookInfo>();

                //foreach (var bookInfo in bookInfos)
                //{
                //    Console.WriteLine($"Book Id: {bookInfo.BookId} Book Name: {bookInfo.BookName} Author Name: {bookInfo.AuthorName}");
                //}

                // This is more manageable than stored procedure
                IEnumerable<Book> books = shopContext.Books.Include( book => book.Author ).ToList();

                foreach (var book in books)
                {
                    Console.WriteLine($"Book Id: {book.BookId} Book Name: {book.Name} Author Name: {book.Author.FirstName+' '+book.Author.LastName}");
                }

            }
        }
    }
}

展开
收起
祖安文状元 2020-01-04 15:16:54 1598 0
1 条回答
写回答
取消 提交回答
  • 您应该为BookInfo使用“ DbQuery”而不是“ DbSet”

    using Microsoft.EntityFrameworkCore;
    using System;
    using System.Collections.Generic;
    using System.Text;
    
    namespace EFCoreShop
    {
        class ShopContext:DbContext
        {
    
            public DbSet<Author> Authors { get; set; }
            public DbSet<Book> Books { get; set; }
            public DbQuery<BookInfo> BookInfos { get; set; }
    
            protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
            {
                optionsBuilder.UseSqlServer("Data Source=**********;Database=EFCoreShop;User ID=*********;Password=***********");
            }
    
    
        }
    }
    
    2020-01-04 15:17:16
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
继承与功能组合 立即下载
开源广进-用Service Catalog构造K8S服务能力 立即下载
低代码开发师(初级)实战教程 立即下载