dotnet / dotnet/EntityFramework.Docs
Document the dangers of using a navigation property to compute the value of a mapped scalar property
- Dominant language
- Mermaid
- Stars
- 1.7k
- Forks
- 2k
- Avg merge
- 7d 23h
- Merged PRs (30d)
- 16
Description
Storing computed property explained in [issue-18998](https://github.com/dotnet/efcore/issues/18998)
But if the computed property dependent on `List Models` which configured as OwnMany, `Models.Clear()` does not update the computed property.
code sample:
```csharp
class Program
{
static async Task Main(string[] args)
{
//Arrange
var seed = new Blog
{
Posts = new List
{
new Post {Title = "one"},
new Post {Title = "two"},
}
};
await using (var ctx = new BlogContext())
{
await ctx.Database.EnsureDeletedAsync();
await ctx.Database.EnsureCreatedAsync();
ctx.Blogs.Add(seed);
ctx.SaveChanges();
}
//Act + Assert
await using (var ctx = new BlogContext())
{
var blog = await ctx.Blogs.FindAsync(seed.Id);
Console.WriteLine(blog.HasPosts); //true
blog.Posts.Clear(); //changing here
Console.WriteLine(blog.HasPosts); //false
var isHasPostsModified =
ctx.ChangeTracker.Entries().Single().Property(p => p.HasPosts).IsModified;
Console.WriteLine(isHasPostsModified); //false, but should be true!
//DELETE FROM "Post"
//WHERE "BlogId" = @p0 AND "Id" = @p1;
//DELETE FROM "Post"
//WHERE "BlogId" = @p2 AND "Id" = @p3;
ctx.SaveChanges(); //No UPDATE HasPosts Statemet!
}
}
public class BlogContext : DbContext
{
public DbSet Blogs { get; set; }
static ILoggerFactory ContextLoggerFactory
=> LoggerFactory.Create(b => b.AddConsole().AddFilter("", LogLevel.Information));
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.UseNpgsql(@"Host=localhost;Username=test;Password=test")
//.UseInMemoryDatabase("dbName");
.EnableSensitiveDataLogging()
.UseLoggerFactory(ContextLoggerFactory);
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity().Property(b => b.Id);
modelBuilder.Entity().HasKey(b => b.Id);
//https://github.com/dotnet/efcore/issues/18998
modelBuilder.Entity()
.Property(r => r.HasPosts)
.UsePropertyAccessMode(PropertyAccessMode.Property);
modelBuilder.Entity().OwnsMany(b => b.Posts,
builder => builder.Property(p => p.Title));
}
}
public class Blog
{
public int Id { get; set; }
public bool HasPosts
{
get => Posts != null && Posts.Any();
private set { } // https://github.com/dotnet/efcore/issues/13316
}
public List Posts { get; set; }
}
public class Post
{
public string Title { get; set; }
}
}
```
EF Core version:
Database provider: approved on Microsoft.EntityFrameworkCore.InMemory / PostgreSQL
```
Contributor guide
Assessment
This issue has not been assessed yet.