Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NullReferenceException when attempting to explicitly map a proxy type #15958

Closed
ibasin opened this issue Jun 5, 2019 · 6 comments · Fixed by #20130
Closed

NullReferenceException when attempting to explicitly map a proxy type #15958

ibasin opened this issue Jun 5, 2019 · 6 comments · Fixed by #20130
Assignees
Labels
area-model-building closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported punted-for-3.0 type-bug
Milestone

Comments

@ibasin
Copy link

ibasin commented Jun 5, 2019

Attempting to create an application that connects to two databases seems to fail. For example, if I try to connect to SQLite and InMemory database at the same time (other combinations also fail), attempt to access ChangeTracker on the second DbContext results in a System.NullReferenceException: 'Object reference not set to an instance of an object.' This exception appears to happen in the ChangeTracker getter.

See the exception details below:

Exception message: System.NullReferenceException: 'Object reference not set to an instance of an object.'
System.NullReferenceException
  HResult=0x80004003
  Message=Object reference not set to an instance of an object.
  Source=Microsoft.EntityFrameworkCore
  StackTrace:
   at Microsoft.EntityFrameworkCore.Metadata.Internal.PropertyParameterBindingFactory.GetCandidatePropertyNames(String parameterName)
   at Microsoft.EntityFrameworkCore.Metadata.Internal.PropertyParameterBindingFactory.TryBindParameter(IMutableEntityType entityType, Type parameterType, String parameterName)
   at Microsoft.EntityFrameworkCore.Metadata.Internal.ConstructorBindingFactory.<>c__DisplayClass3_0.<TryBindConstructor>b__0(ParameterInfo p)
   at System.Linq.Enumerable.SelectArrayIterator`2.ToList()
   at Microsoft.EntityFrameworkCore.Metadata.Internal.ConstructorBindingFactory.TryBindConstructor(IMutableEntityType entityType, ConstructorInfo constructor, ConstructorBinding& binding, IEnumerable`1& failedBindings)
   at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConstructorBindingConvention.Apply(InternalModelBuilder modelBuilder)
   at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.ImmediateConventionScope.OnModelBuilt(InternalModelBuilder modelBuilder)
   at Microsoft.EntityFrameworkCore.Metadata.Internal.Model.FinalizeModel()
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.CreateModel(DbContext context, IConventionSetBuilder conventionSetBuilder, IModelValidator validator, DiagnosticsLoggers loggers)
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.<>c__DisplayClass5_0.<GetModel>b__1()
   at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
   at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
   at System.Lazy`1.CreateValue()
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.GetModel(DbContext context, IConventionSetBuilder conventionSetBuilder, IModelValidator validator, DiagnosticsLoggers loggers)
   at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel()
   at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model()
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
   at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
   at Microsoft.EntityFrameworkCore.DbContext.get_ChangeTracker()
   at EFCoreTester.Program.<Main>d__0.MoveNext() in C:\Users\ilyabasin\Documents\Projects\TDM.Core\Frameworks\Testers\EFCoreTester\Program.cs:line 30

Steps to reproduce

The error is easy to reproduce.

Use the following code snippet to reproduce:

            using (var context = new InMemoryDbContext())
            {
                var ct = context.ChangeTracker;
                context.Set<Author>().Add(new Author { Name = "Author1" });
                await context.SaveChangesAsync();
            }

            using (var context = new SqliteDbContext())
            {
                var ct = context.ChangeTracker;
                context.Set<Author>().Add(new Author { Name = "Author2" });
                await context.SaveChangesAsync();
            }

Both SqliteDbContext and InMemoryDbContext are plain vanilla. Just note that I have lazy loading turned on for both contexts.

Further technical details

EF Core version: 3.0.0-preview5.19227.1
Database Provider: Microsoft.EntityFrameworkCore.Sqlite & Microsoft.EntityFrameworkCore.InMemory
Operating system: Windows 10
IDE: Visual Studio 2019 Preview

@ajcvickers
Copy link
Member

@ibasin I have not been able to reproduce this--see my code below. Can you post a small, runnable project/solution or complete code listing (like below) that reproduces what you are seeing?

public class Author
{
    public int Id { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Book> Books { get; set; }
}

public class Book
{
    public int Id { get; set; }
    public string Name { get; set; }
    
    public int AuthorId { get; set; }
    public virtual Author Author { get; set; }
}

public class InMemoryDbContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) 
        => optionsBuilder
            .UseLazyLoadingProxies()
            .UseInMemoryDatabase("In-mem");

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Author>();
    }
}

public class SqliteDbContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) 
        => optionsBuilder
            .UseLazyLoadingProxies()
            .UseSqlite("Data Source = sqllitetest.db");

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Author>();
    }
}

public class Program
{
    public static async Task Main()
    {
        using (var context = new InMemoryDbContext())
        {
            context.Database.EnsureCreated();

            var ct = context.ChangeTracker;
            context.Set<Author>().Add(new Author { Name = "Author1" });
            await context.SaveChangesAsync();
        }

        using (var context = new SqliteDbContext())
        {
            context.Database.EnsureCreated();

            var ct = context.ChangeTracker;
            context.Set<Author>().Add(new Author { Name = "Author2" });
            await context.SaveChangesAsync();
        }
    }
}

@ibasin
Copy link
Author

ibasin commented Jun 5, 2019

Please see attached a simple solution that reproduces the problem.

MultiRepoTest.zip

@ajcvickers
Copy link
Member

@ibasin This is happening because the code is attempting to register a dynamically generated proxy as an entity type:
image
We should throw a better exception for this.

@ibasin
Copy link
Author

ibasin commented Jun 5, 2019

@ajcvickers

Thank you! This makes perfect sense. The second one picks up the dynamic proxies generated by the first one. Fixed !

@ibasin ibasin closed this as completed Jun 5, 2019
@ajcvickers ajcvickers reopened this Jun 5, 2019
@ajcvickers ajcvickers added this to the 3.0.0 milestone Jun 6, 2019
@ajcvickers ajcvickers self-assigned this Jun 6, 2019
@ajcvickers
Copy link
Member

Triage: better exception.

@ajcvickers ajcvickers changed the title EFCore does not seem to allow to mix DbContexts to different databases in one app NullReferenceException when attempting to explicitly map a proxy type Jun 6, 2019
@ajcvickers ajcvickers modified the milestones: 3.0.0, Backlog Jun 28, 2019
@ajcvickers ajcvickers modified the milestones: Backlog, 5.0.0 Nov 13, 2019
@lajones lajones assigned lajones and unassigned ajcvickers Mar 2, 2020
@lajones
Copy link
Contributor

lajones commented Mar 2, 2020

Poaching.

@lajones lajones added the closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. label Mar 4, 2020
@ajcvickers ajcvickers modified the milestones: 5.0.0, 5.0.0-preview2 Mar 13, 2020
@ajcvickers ajcvickers modified the milestones: 5.0.0-preview2, 5.0.0 Nov 7, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-model-building closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported punted-for-3.0 type-bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants