Search code examples
aspnetboilerplate

How to update the entity in aspnetboilerplate?


I want to update an entity in database. I use the aspnetboilerplate template project. I have a method UpdateAsset in the application layer:

public async Task UpdateAsset(UpdateAssetInput input)
    {
        var asset = ObjectMapper.Map<Asset>(input.Asset);
        asset.Domain = asset.Domain.ToLowerInvariant();

        // Update Twitter Id
        var twitterName = input.Asset.SocialAccounts?.TwitterInfo?.Name;
        if (twitterName != null)
        {
            var twitterId = await _twitterActivityManager.GetTwitterIdByTwitterName(twitterName);
            if (twitterId != null)
            {
                input.Asset.SocialAccounts.TwitterInfo.Id = twitterId;
            }
        }

        asset.SetData<SocialAccounts>(AssetExtensionData.SocialAccounts, input.Asset.SocialAccounts);
        var connectedAsset = await _assetManager.GetAsset(input.Asset.LockedPositionInfo.ConnectedAssetId);
        if (connectedAsset != null)
        {
            input.Asset.LockedPositionInfo.ConnectedAssetUnit = connectedAsset.Unit;
        }
        asset.SetData<LockedPositionInfo>(AssetExtensionData.LockedPositionInfo, input.Asset.LockedPositionInfo);
        asset.SetData(AssetExtensionData.WithdrawalApiInfo, input.Asset.WithdrawalApiInfo);
        await _assetManager.UpdateAsset(asset);
    }

UpdateAssetInput:

public class UpdateAssetInput
{
    public AssetDto Asset { get; set; }
}

AssetDto:

[AutoMap(typeof(Asset))]
public class AssetDto : AuditedEntityDto<string>
{
    public const int SYMBOL_LENGTH = 10;

    [Required]
    [MaxLength(SYMBOL_LENGTH)]
    public new string Id { get; set; }

    [Required]
    public string Name { get; set; }

    public string Description { get; set; }

    public string Website { get; set; }

    [Required]
    public string Domain { get; set; }

    public string Logo { get; set; }

    public string Organization { get; set; }

    public string Unit { get; set; }

    public SocialAccounts SocialAccounts { get; set; }

    public LockedPositionInfo LockedPositionInfo { get; set; }

    public WithdrawalApiInfo WithdrawalApiInfo { get; set; }


    public decimal TotalAmount { get; set; }

    public decimal Price { get; set; }

    public bool IsDisable { get; set; } = false;
}

UpdateAsset in the AssetManager:

public async Task UpdateAsset(Asset asset)
    {
        try
        {
            await _assetRepository.UpdateAsync(asset);
        }
        catch (Exception e)
        {
            Logger.Error(e.Message, e);
            throw new UserFriendlyException(L("AssetUpdateFailed"), asset.Name);
        }
    }

When I call the UpdateAsset of the application layer in front end, I get the exception:

System.InvalidOperationException: 'The instance of entity type 'Asset' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. 

So how to solve the problem ?


Solution

  • Normally, when we update a asset entity, we will do following 3 steps:

    1. Get asset entity from db
    2. set updated value to asset entity
    3. Update asset entity

    based on your error message, you may get asset entity from db twice

    1. Get asset1 entity from db - tracked
    2. Get asset2 entity from db - tracked
    3. set updated value to asset2 entity
    4. Update asset2 entity

    Please check if you have above code snippet