zzzprojects / EntityFramework-Extensions

Entity Framework Bulk Operations | Improve Entity Framework performance with Bulk SaveChanges, Insert, update, delete and merge for SQL Server, SQL Azure, SQL Compact, MySQL and SQLite.
https://entityframework-extensions.net
342 stars 57 forks source link

BulkMerge - `IncludeGraph` feature not work with InMemoryDatabase #373

Open tien199013 opened 3 years ago

tien199013 commented 3 years ago

Description

When adding unit tests for a business logic where touching BulkMerge with IncludeGraph feature, we got the following exceptions. Surprisingly, the production code works and behaves as what we expected. However, in the unit tests stage where we using the EF core's in memory database it failed.

Exception

If you are seeing an exception, include the full exceptions details (message and stack trace). System.Exception: Oops! The 'IncludeGraph' feature doesn't work with 'BulkUpdate' and 'BulkMerge' NMemory provider. at .(DbContext this, Action1 , DbContext ) at DbContextExtensions.(DbContext this, Action1 , DbContext ) at .BulkMerge[T](DbContext this, IEntityType entityType, IEnumerable1 list, Action1 options, Boolean forceSpecificTypeMapping) at .BulkMerge[T](DbContext this, IEnumerable1 entities, Action1 options) at DbContextExtensions.BulkMerge[T](DbContext this, IEnumerable1 entities, Action1 options) at DbContextExtensions.1.() at System.Threading.Tasks.Task.InnerInvoke() at System.Threading.Tasks.Task.<>c.<.cctor>b__274_0(Object obj) at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state) --- End of stack trace from previous location where exception was thrown --- at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread) --- End of stack trace from previous location where exception was thrown --- at DbContextExtensions.BulkMergeAsync[T](DbContext this, IEnumerable1 entities, Action`1 options, CancellationToken cancellationToken)

Example code

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

namespace A.Tests
{
    public class Tests
    {
        [Fact]
        void Should_pass()
        {
            using (var context = new BookStore())
            {
                var authors = new List<Author>
                {
                    new Author
                    {
                        FirstName ="Carson",
                        LastName ="Alexander",
                        BirthDate = DateTime.Parse("1985-09-01"),
                        Books = new List<Book>()
                        {
                            new Book { Title = "Introduction to Machine Learning"},
                            new Book { Title = "Advanced Topics on Machine Learning"},
                            new Book { Title = "Introduction to Computing"}
                        }
                    },
                    new Author
                    {
                        FirstName ="Meredith",
                        LastName ="Alonso",
                        BirthDate = DateTime.Parse("1970-09-01"),
                        Books = new List<Book>()
                        {
                            new Book { Title = "Introduction to Microeconomics"}
                        }
                    },
                    new Author
                    {
                        FirstName ="Arturo",
                        LastName ="Anand",
                        BirthDate = DateTime.Parse("1963-09-01"),
                        Books = new List<Book>()
                        {
                            new Book { Title = "Calculus I"},
                            new Book { Title = "Calculus II"}
                        }
                    }
                };

                //IncludeGraph allows you to INSERT/UPDATE/MERGE entities by including the child entities graph.
                context.BulkMerge(authors, options => options.IncludeGraph = true);
            }

            using (var context = new BookStore())
            {
                var list = context.Authors
                    .Include(a => a.Books)
                    .ToList();

                foreach (var author in list)
                {
                    Console.WriteLine(author.FirstName + " " + author.LastName);

                    foreach (var book in author.Books)
                    {
                        Console.WriteLine("\t" + book.Title);
                    }
                }
            }
        }

    }

    public class BookStore : DbContext
    {
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseInMemoryDatabase(databaseName: "BookStoreDb");
        }

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

    public class Author
    {
        public int AuthorId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public DateTime BirthDate { get; set; }
        public List<Book> Books { get; set; }
    }

    public class Book
    {
        public int BookId { get; set; }
        public string Title { get; set; }
        public Author Author { get; set; }
    }
}

Further technical details

JonathanMagnan commented 3 years ago

Hello @tien199013 ,

Unfortunately, we have disabled the support of IncludeGraph for InMemory provider.

The problem happens due to how the context works under the hood for the InMemory provider. We will eventually re-work the IncludeGraph feature to stop using some EF Core method but for now, there is nothing we can do since that's not a quick fix and a lot of big development is already ongoing on this library to better support EF Core 5.

Best Regards,

Jon

daxstar83 commented 2 years ago

HI, is there any further development regarding the problem with IncludeGraph and the InMemory Db provider ?

Best Regards, Rico

JonathanMagnan commented 2 years ago

Hello @daxstar83 ,

Unfortunately there is currently no progress

mbikodusic commented 2 years ago

What is the latest EF Plus version where this was supported? Do you have any timeline when this can be expected?