EFCore ValueObject 未将父级标记为已更改?

问题描述 投票:0回答:3

您好,我有一个实体“人”。使用“别名”值对象

 public partial class Person : BaseEntity, IAggregateRoot
{
  public Alias Alias { get; set; }
  //..other properties...

}

PersonConfiguration.cs

entity.OwnsOne(o => o.Alias, a =>
{
   a.WithOwner(x=>x.Person);
});

别名

public class Alias :ValueObject
{
 public string FirstName { get; private set; }
 public string MiddleName { get; private set; }
 public string LastName { get; private set; }
}

如果我对 Alias 上的属性进行更改 - 更改名字 - 它不会在更改跟踪器中将该人标记为已更改。我已经使用变更跟踪器完成了审核。因此,如果我只是更改别名上的属性,则不会设置最后更新日期和用户。

我可以做些什么来解决这个问题吗?

谢谢你。

c# .net entity-framework entity-framework-core domain-driven-design
3个回答
1
投票

创建 EntityEntry 扩展

public static bool HasChangedOwnedEntities(this EntityEntry entry)
   => entry.References.Any(r => r.TargetEntry != null &&
      r.TargetEntry.MetaData.IsOwned() && 
      r.TargetEntry.State == EntityState.Added || 
      r.TargetEntry.State == EntityState.Modified)

然后在盒子里调用它

EntityState.Unchanged

if (entry.HasChangedOwnedEntities())
{
   entry.Entity.LastModidfiedBy = userId;
   entry.Entity.LastModidfied = _datetime.Now;
}

0
投票

找到了一种方法 - 对此并不感到兴奋,但它有效..

var ownedEntries = _context.ChangeTracker.Entries<ValueObject>().Where(f => f.Metadata.IsOwned() && f.State == EntityState.Modified).ToList();
foreach (var item in ownedEntries)
{
    var ownedNavigations = item.Metadata.GetNavigations().Where(n => n.ForeignKey.IsRequiredDependent).ToList();
    foreach (var nav in ownedNavigations)
    {
        var ownerEntry = item.Reference(nav.Name).TargetEntry;
        if (ownerEntry != null)
        {
            // Get the owner entity using reflection
            var ownerEntity = ownerEntry.Entity
            // Set the owner entity as modified
            var ownerEntryType = ownerEntry.GetType();
            var stateProperty = ownerEntryType.GetProperty("State", BindingFlags.Public | BindingFlags.Instance);
            stateProperty?.SetValue(ownerEntry, EntityState.Modified);
        }
    }
} 

0
投票

值对象应该是不可变的。创建值对象后,您不应该更改它的属性。

不要更改 Alias 的属性,而是替换它。

Person.Alias = new Alias("John", "Robert", "Smith");
// Change name
Person.Alias = Person.Alias.ChangeFirstName("Dave");

别名(使用

init
setter 强制执行不变性)

public string FirstName { get; init; }
public string MiddleName { get; init; }
public string Surname { get; init; }

public Alias(string firstName, string middleName, string surname)
{
    FirstName = firstName;
    MiddleName = middleName;
    Surname = surname;
}

public Alias ChangeFirstName(string newFirstName) =>
    new Alias(newFirstName, MiddleName, Surname);
© www.soinside.com 2019 - 2024. All rights reserved.