TrackableEntities / TrackableEntities.Core

Change-tracking across service boundaries with .NET Core.
MIT License
74 stars 13 forks source link

ApplyChanges on entity with FK entity fails. #32

Closed yannickdp closed 5 years ago

yannickdp commented 5 years ago

Hi Tony,

I'm having an issue when ApplyChangesfor a given entity which has an unchanged FK related entity.

Consider the next entity class:

/// <summary>
/// Entity class representing data for table 'Product'.
/// </summary>
public partial class Product : SelfTrackedEntity, ISoftDeletable
{
    #region Private fields

    private bool _containsAllergens;
    private bool _isContaminated;
    private bool _isRecipeUpdated;
    private int? _productTypeId;

    #endregion

    #region Properties

    public bool ContainsAllergens
    {
        get => _containsAllergens;
        set => SetProperty(ref _containsAllergens, value);
    }

    public bool IsContaminated
    {
        get => _isContaminated;
        set => SetProperty(ref _isContaminated, value);
    }

    public bool IsRecipeUpdated
    {
        get => _isRecipeUpdated;
        set => SetProperty(ref _isRecipeUpdated, value);
    }

    public int? ProductTypeId
    {
        get => _productTypeId;
        set
        {
            SetProperty(ref _productTypeId, value);
            this.SetRelationById<Product, int, int?>(ref _productTypeId, value, (e) => e._productType = null);
        }
    }

    #endregion

    #region Relationships

    private ProductType _productType;
    public virtual ProductType ProductType
    {
        get => _productType;
        set => this.SetRelationByObject<Product, int, ProductType, int>(ref _productType, value, (e, id) => { e._productTypeId = id; SetProperty(ref e._productTypeId, id); });
    }

    #endregion

}

Some explanation about this product entity:

Situation:


ProductType productType;
using (var unitOfWork = _unitOfWorkFactory.Create())
{
      var productTypeRepository = unitOfWork.GetService<IProductTypeRepository>();
      var productTypes = await productTypeRepository.GetAllAsync(q => q.SetTop(1));

      productType = productTypes.First();

      await unitOfWork.SaveChanges();
}

var p = new Product
{
      ContainsAllergens = false,
      IsContaminated = false,
      IsRecipeUpdated = false,
      ProductType = productType
};

using (var unitOfWork = _unitOfWorkFactory.Create())
{
      var productRepository = unitOfWork.GetService<IProductRepository>();

      productRepository.Add(p);
      productRepository.ApplyChanges(p);

      await unitOfWork.SaveChanges();
}

Some explanation about the code above:

This is incorrect in my opinion because the TrackingState of this ProductType entity is still unchanged. So why saving this in the Database at this point? Should the ApplyChanges not have to take the TrackingState into account to skip unchanged FK entities from being added again as Detached entities to the DbContext? Or at least should this not be an option to pass to the ApplyChanges to attach only the parent level entities and not the complete graph?