dotnet / dotnet/efcore

Shared owned type ToJson not working with ChangeTrackingProxies

Open
#32,660 1 comment 0 reactions 0 assignees View on GitHub
area-proxies customer-reported
Dominant language
C#
Stars
14.8k
Forks
3.4k
PR merge metrics
PR metrics pending

Description

ToJson owned types seem to work correctly with ChangeTrackingProxies, except when the type is "shared". Take the following minimal repro code:
```C#
using Microsoft.EntityFrameworkCore;
namespace ToJsonWithProxiesTest;

public class Customer
{
public virtual int Id { get; set; }
public virtual required string Name { get; set; }
// public virtual Address? BillingAddress { get; set; }
public virtual Address? ShippingAddress { get; set; }
}

public class Address
{
public virtual string? Street { get; set; }
public virtual string? Town { get; set; }
}

public class MyDbContext : DbContext
{
public DbSet Customers { get; set; }

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("server=.;database=workspace;trusted_connection=true;");
optionsBuilder.UseLazyLoadingProxies();
optionsBuilder.UseChangeTrackingProxies();
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity()
.ToTable("Customer")
// .OwnsOne

(e => e.BillingAddress, b => b.ToJson())
.OwnsOne
(e => e.ShippingAddress, b => b.ToJson());
}
}

internal class Program
{
static void Main(string[] args)
{
using var context1 = new MyDbContext();
var person = context1.Customers.CreateProxy();
person.Name = "Jane Doe";
person.ShippingAddress = context1.CreateProxy

();
person.ShippingAddress.Street = "5th Avenue";
person.ShippingAddress.Town = "NY";
context1.Add(person);
context1.SaveChanges();
}
}
```

This code actualy runs fine.

Problem arrises when the Address type is reused. Uncomment the two commented lines (definition of BillingAddress property and it's ToJson mapping in OnModelCreating), and this same code results in following exception:
```
Unhandled exception. System.InvalidOperationException: The type 'Address' is configured as a shared-type entity type, but the entity type name is not known. Ensure that CreateProxy is called on a DbSet created specifically for the shared-type entity type through use of a 'DbContext.Set' overload that accepts an entity type name.
at Microsoft.EntityFrameworkCore.Proxies.Internal.ProxyFactory.Create(DbContext context, Type type, Object[] constructorArguments)
at Microsoft.EntityFrameworkCore.ProxiesExtensions.CreateProxy(IServiceProvider serviceProvider, Type entityType, Object[] constructorArguments)
at Microsoft.EntityFrameworkCore.ProxiesExtensions.CreateProxy(DbContext context, Type entityType, Object[] constructorArguments)
at Microsoft.EntityFrameworkCore.ProxiesExtensions.CreateProxy[TEntity](DbContext context, Action`1 configureEntity, Object[] constructorArguments)
at Microsoft.EntityFrameworkCore.ProxiesExtensions.CreateProxy[TEntity](DbContext context, Object[] constructorArguments)
at ToJsonWithProxiesTest.Program.Main(String[] args) in C:\Trash\TrashProjects\ToJsonWithProxiesTest\ToJsonWithProxiesTest\ProgramMinimal.cs:line 45
```

Project is a Console app that targets net8.0 and has following package references
```

```

Visual Studio 2022 version 17.8.3
Windows 10 Pro 22H2, build 19045.3803

SQL Server table creation script:
```
CREATE TABLE [dbo].[Customer] (
[Id] int IDENTITY(1,1) NOT NULL,
[Name] NVARCHAR(200) NOT NULL,
[BillingAddress] NVARCHAR(MAX) NULL,
[ShippingAddress] NVARCHAR(MAX) NULL,
CONSTRAINT [PK_Person] PRIMARY KEY CLUSTERED ([Id] ASC))
GO
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.