首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >带有自定义返回类型的实体框架核心-无法为“BookInfo”创建BookInfo,因为该类型不包含在上下文的模型中

带有自定义返回类型的实体框架核心-无法为“BookInfo”创建BookInfo,因为该类型不包含在上下文的模型中
EN

Stack Overflow用户
提问于 2019-12-28 10:29:52
回答 1查看 1.3K关注 0票数 0

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

我试图使用EFCore3.1从Server查询自定义返回类型。有两个实体图书和作者,我想得到的BookInfo有BookId,BookName,AuthorName。这是以下代码。

存储过程:

代码语言:javascript
复制
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

代码语言:javascript
复制
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; }
    }
}

Author.cs

代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
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核心中使用内部连接。但是,我试图从带有自定义返回类型的存储过程中获取数据。

你能指导我解决这个问题吗?

错误:

代码语言:javascript
复制
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 (没有存储过程,不是我想要的)

代码语言:javascript
复制
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}");
                }

            }
        }
    }
}
EN

回答 1

Stack Overflow用户

发布于 2019-12-28 10:56:39

你应该用“DbQuery”代替“DbSet”来表示BookInfo

代码语言:javascript
复制
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=***********");
        }


    }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59510051

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档