实体框架核心在SaveChanges之前更改实体关系

时间:2018-05-02 14:27:14

标签: c# entity-framework-core

在以通用方式调用SaveChanges之前,有没有办法更新实体关系?

public class Vehicle
{
    public int Id { get; set; }
    public int OwnerId { get; set; }
    [ForeignKey("OwnerId")]
    public Person Owner { get; set; }
}

例如,我想创建新Person,并在生成Id之前(在调用SaveChanges之前)将其分配给Vehicle。我知道我可以这样做:

entry.Property("OwnerId").CurrentValue = newId;

但问题是,在致电SaveChanges之前,我不知道新实体的身份证明。

我想要实现的是在所有者更改时自动创建所有者的副本,并将所有者分配给副本。当然,我必须以某种方式在SaveChanges覆盖中执行。

类似的东西:

public override async Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default(CancellationToken))
{
    foreach (var entry in ChangeTracker.Entries())
    {
       foreach (var reference in entry.References)
       {
          if (reference.TargetEntry != null && reference.TargetEntry.State == EntryState.Modified)
          {
              // make a copy of target entry and update reference to it,
             // note: you can't really add new entries inside this loop as it will throw an exception, so all the adding has to be done outside
            // I would like to set this newEntity as the Owner
            var newEntity = (BaseEntity)entry.CurrentValues.ToObject();
            newEntity.Id = 0;
          }
       }
    }
    return await base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
}

我希望它如何运作:

//would insert new Person row and update OwnerId to point to this new row
vehicle.Owner.Name = "NewName";

1 个答案:

答案 0 :(得分:2)

您应该更新参考,以便在您没有ID时更新ID:

public override async Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default(CancellationToken))
{
    foreach (var entry in ChangeTracker.Entries())
    {
       bool shouldUpdateReference = false;

       foreach (var reference in entry.References)
       {
           if (reference.TargetEntry != null && reference.TargetEntry.State == EntryState.Modified)
           {
               shouldUpdateReference = true;
           }
       }

        // I imagine this has to be done outside the foreach 
        // since you are modifying a reference and that should 
        // update the References collection
        if (shouldUpdateReference)
        {
            entity.Reference("Owner").CurrentValue = newOwner; 
        }
    }

    return await base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
}