简体   繁体   中英

Entity Framework Core with Custom Return Type - Cannot create a DbSet for 'BookInfo' because this type is not included in the model for the context

Entity Framework Core with Custom Return Type

I'm trying to query a Custom Return Type from Sql Server using EF Core 3.1. There are two entities Book and Author and I want to get the BookInfo that has BookId, BookName, AuthorName. Here's the following code.

Stored Procedure:

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; }
    }
}

Author.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}");
                } 
            }
        }
    }
}

I think I have done everything good. I'm trying to return a custom type from the database and already have the store procedure in there. I don't want the entity to be mapped either.

Note: I know I can do it using inner join in EF Core. But, I'm trying to get the data from stored procedure with custom return type.

Could you guide me in fixing the issue.

Error:

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

UPDATE:
This code below would solve the issue without using Stored Procedure. But, we want result using Stored Procedure. However, if you don't want to use Stored Procedure you can do this as well.

Program.cs ( without store procedure, not what I want)

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}");
                }

            }
        }
    }
}

you should use 'DbQuery' instead of 'DbSet' for your BookInfo

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=***********");
        }


    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM