Open fasoltanzadeh opened 10 months ago
@fasoltanzadeh How are you configuring lazy-loading? Does it not throw saying that "ORMAProfileAccessor" cannot be overridden?
@fasoltanzadeh How are you configuring lazy-loading? Does it not throw saying that "ORMAProfileAccessor" cannot be overridden?
@ajcvickers No It does work perfectly and it fills the database correctly, Here is the config for lazy loading:
optionsBuilder.UseLazyLoadingProxies();
Note for triage: underlying issue here is that internal
properties are considered valid for lazy-loading, but then don't work because they cannot be overridden. Simple repro:
using (var context = new SomeDbContext())
{
await context.Database.EnsureDeletedAsync();
await context.Database.EnsureCreatedAsync();
context.Add(new Pool { ORMAProfileAccessor = new AProfile() } );
await context.SaveChangesAsync();
}
using (var context = new SomeDbContext())
{
var pool = context.Set<Pool>().Single();
Console.WriteLine(pool.ORMAProfileAccessor);
}
public class SomeDbContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.UseSqlServer(@"Data Source=(LocalDb)\MSSQLLocalDB;Database=AllTogetherNow")
.UseLazyLoadingProxies()
.LogTo(Console.WriteLine, LogLevel.Information)
.EnableSensitiveDataLogging();
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<AProfile>().HasOne(P => P.Pool).WithOne(Q => Q.ORMAProfileAccessor).HasForeignKey<Pool>("AProfileId").IsRequired(false);
}
}
public class Pool
{
public int Id { get; set; }
internal virtual AProfile ORMAProfileAccessor { get; set; }
}
public class AProfile
{
public int Id { get; set; }
public virtual Pool? Pool { get; set; }
}
ITNOA
I have same issue
I have the same issue here.
@ajcvickers I'm not sure if its directly related to internal
properties. I'm protecting all of my navigation properties (Collection<T>
most of the time) by marking them as internal
.
So I make them visible to EF
using (in .csproj
file):
<ItemGroup>
<InternalsVisibleTo Include="Application.Data"/>
</ItemGroup>
I haven't seen any issue with Collections
.
@ajcvickers Did you have any time estimate to resolve this issue?
@soroshsabz This issue is tracking making EF throw in model validation when internal navigations are used in lazy-loading proxies. The reason the navigation is null is that proxies cannot override internal methods, since they are not visible to the proxy assembly. This isn't a critical bug to fix, since the scenario is already invalid, it should just throw with a better exception message.
@ajcvickers as you can see in @Reza-Noei comments, internal
accessor does not cause of this problem, I have many project with internal
accessor (and <InternalsVisibleTo Include="Assembly"/>
) and works correctly too.
So I do not think the root cause of the problem from this place
@ajcvickers I think you can probably reproduce this bug, without using any internal
too.
such as below code
public class Pool
{
public int Id { get; set; }
public Profile? Profile
{
get
{
return ORMAProfileAccessor as Profile ?? ORMBProfileAccessor;
}
set
{
switch (value)
{
case AProfile aProfile:
ORMAProfileAccessor = aProfile;
break;
case BProfile bProfile:
ORMBProfileAccessor = bProfile;
break;
default:
throw new InvalidCastException("Invalid profile type");
}
}
}
public virtual AProfile? ORMAProfileAccessor { get; set; }
public virtual BProfile? ORMBProfileAccessor { get; set; }
}
public abstract class Profile
{
public Profile() { }
public int Id { get; set; }
}
public class AProfile : Profile
{
public AProfile() { }
public virtual Pool? Pool { get; set; }
}
public class BProfile : Profile
{
public BProfile() { }
public virtual Pool? Pool { get; set; }
}
@ajcvickers I add some complete project for reproducing this problem, without using any internal
in https://github.com/soroshsabz/TestSolution/tree/main/Source/ConsoleTest/ConsoleApp1
Please see it
thanks :)
@soroshsabz That code doesn't use lazy-loading. When I add lazy-loading proxies, then I get:
C:\Users\avickers\AppData\Local\Programs\Rider\plugins\dpa\DotFiles\JetBrains.DPA.Runner.exe --handle=19956 --backend-pid=31380 --etw-collect-flags=3 --detach-event-name=dpa.detach.19956 C:/local/code/AllTogetherNow/Daily/bin/Debug/net8.0/Daily.exe
Hello, World!
Pool2: 1
Pool2.Profile: 2
Pool2: 1
Pool2.Profile: 2
@ajcvickers Sorry, I mistake.
I have question, why proxy could not override internal
navigation when I set <InternalsVisibleTo Include="Assembly"/>
?
Note for triage: verified that lazy-loading works with [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
. Putting on the backlog to throw when attempting to load if the navigation exists but is not visible.
I'm encountering an issue with Entity Framework Core (EF Core) related to lazy loading, inheritance, and property retrieval. Initially, I had the following entity classes:
In the OnModelCreating method, I configured the relationships as follows:
The issue I'm facing now is that after saving a Pool object to the database with associated Profile, upon retrieving the Pool elsewhere in the code, the Profile field remains null. However, retrieving a Profile separately shows that the Pool field within the Profile object is correctly populated. For example:
How can I ensure that when retrieving a Pool, the Profile field is populated with the associated Profile type?
Any insights or suggestions would be highly appreciated. Thank you!
EF Core version: 6.0.16 Database provider:Microsoft.EntityFrameworkCore.SqlServer Target framework: .NET 6.0 IDE: Visual Studio 2022 17.4