EfCore owned property state for parent entity

Arnaud Boussaer 0 Reputation points
2024-12-02T13:37:34.0566667+00:00

Hi,

I use EfCore v8 with some Json columns. My code:

// Parent entities
public class Project
{
    public Guid Id { get; set; }
    public string Name { get; set; }

    public ICollection<KolomMetadata> KolomMetadata { get; set; }
}
public class Werkpakket
{
    public Guid Id { get; set; }
    public string Name { get; set; }

    public ICollection<KolomMetadata> KolomMetadata { get; set; }
}

// Owned Type
public class KolomMetadata {
	public string Kolomnaam { get; set; }
	public DateTimeOffset? SomeDate { get; set; }
	//... other columns
}

// Configuration
public class ProjectMap : IEntityTypeConfiguration<Project>
{
    public void Configure(EntityTypeBuilder<Project> builder)
    {
        builder.OwnsMany(t => t.KolomMetadata, builder => builder.ToJson());
    }
}

//Execution code:
//I modify the owned property collection of an instance
project.KolomMetadata.First().SomeDate = DateTimeOffset.Now;

// I want to find all projects which are modified, both project and project.KolomMetadata modifications
var projectsModified = _dbContext.ChangeTracker
    .Entries<Project>()
    .Any(x => x.State == EntityState.Modified);

Console.WriteLine(projectsModified.Any());  // -> false 

I want to be able to detect State changes on parent entity level (eg. Project, Werkpakket) when the owned property (collection of KolomMetadata) is modified (KolomMetadata entries added, removed and modified). How can I achieve this?

Developer technologies | .NET | Entity Framework Core
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Anonymous
    2024-12-03T06:57:17.21+00:00

    Hi,@Arnaud Boussaer. Welcome to Microsoft Q&A. 

    Currently, there seems to be no good way to directly monitor changes in KolomMetadata and modify the State through configuration. You could manually modify the State when modifying KolomMetadata.

    project.KolomMetadata.First().SomeDate = DateTime.Now;
    _dbContext.Entry(project).State = EntityState.Modified;
    

    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


  2. Arnaud Boussaer 0 Reputation points
    2024-12-05T11:13:49.74+00:00

    Thank you for your suggestion. It is indeed a good solution!

    I also found a solution which has a better performance (10 to 90% faster):

    var modifiedKolomMetadataEntities = ChangeTracker.Entries<KolomMetadata>()
        .Where(p => p.State == EntityState.Modified || p.State == EntityState.Added || p.State == EntityState.Deleted);
    /* An owned entity (KolomMetadata) has two shadow properties:
     * - Id: the internal unique id of the owned entity (here an int)
     * - 'external id': the id of the parent/owned entity (here a Guid)
     * 
     * To retrieve the second one, we search for the shadow property which doesn't have the name "Id"
     */
    var linkedMemberIds = modifiedKolomMetadataEntities
        .Select(e => Guid.Parse(e.Members.First(m => m.Metadata.IsShadowProperty() && m.Metadata.Name != "Id").CurrentValue.ToString()))//get the parent entity id
        .ToHashSet();
    if (linkedMemberIds.Any())
        return ChangeTracker.Entries<Project>()
            .Where(e => linkedMemberIds.Contains(e.Entity.Id));
    
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.