entity-framework-corelazy-loadingef-core-2.2owned-types

Entity Framework Core 2.2 Owned Entity with UseLazyLoadingProxies


I am currently working on a codebase, to which I want to add a number of new entities with corresponding owned entities. Because, in some other part of the codebase I won't touch, UseLazyLoadingProxies is called; I receive the following exception:

System.InvalidOperationException : Navigation property 'Foo' on entity type 'FooOwner' is not virtual. UseLazyLoadingProxies requires all entity types to be public, unsealed, have virtual navigation properties, and have a public or protected constructor.

If I mark the property as virtual, the owned entity goes into a new table; which I do not want either.

According to github issues I encountered, these seem to be the expected behavior.

My question is this: Is there a way to work around this problem, such that, I can somehow mark the owned entity to be stored in the same table as the owner entity, and if possible to be always Included, eagerly loaded.

using System.Diagnostics;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using NUnit.Framework;

namespace StackOverflowObjectContext.Tests
{
    public class Foo
    {
        public long Id { get; set; }
        public int Data { get; set; }
    }

    public class FooOwner
    {
        public int Id { get; set; }

        public Foo Foo { get; set; }
    }

    public class FooOwnerMap : IEntityTypeConfiguration<FooOwner>
    {
        public void Configure(EntityTypeBuilder<FooOwner> builder)
        {
            builder.HasKey(x => x.Id);
            builder.HasOne(x => x.Foo);
        }
    }

    public class StackOverflowObjectContext : DbContext
    {
        public StackOverflowObjectContext(DbContextOptions options) : base(options) { }

        DbSet<FooOwner> FooOwners { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.ApplyConfiguration(new FooOwnerMap());
            base.OnModelCreating(modelBuilder);
        }
    }

    [TestFixture]
    public class StackOverflowTest
    {
        StackOverflowObjectContext _objectContext;

        [SetUp]
        public void SetUp()
        {
            var builder = new DbContextOptionsBuilder<StackOverflowObjectContext>()
                .UseSqlServer(@"Data Source=.\SQLEXPRESS;Initial Catalog=StackOverflow;Integrated Security=True")
                .UseLazyLoadingProxies();

            _objectContext = new StackOverflowObjectContext(builder.Options);
        }


        [Test]
        public void CanGenerateCreateScript()
        {
            var script = _objectContext.Database.GenerateCreateScript();

            Debug.WriteLine(script);
        }

    }
}

Solution

  • You should use OwnsOne instead of HasOne