Base solution for your next web application
Starts in:
01 DAYS
01 HRS
01 MIN
01 SEC
Open Closed

attaching an entity of type 'x' failed #1738


User avatar
0
moustafa created

Hello

i'm trying to update record but must be sure to prevent updating some fields so i retrieve the old record before editing but i got this error nHandling.AbpApiExceptionFilterAttribute - Attaching an entity of type 'Umbrella.Models.Patient.Patient' failed because another entity of the same type already has the same primary key value. This can happen when using the 'Attach' method or setting the state of an entity to 'Unchanged' or 'Modified' if any entities in the graph have conflicting key values. This may be because some entities are new and have not yet received database-generated key values. In this case use the 'Add' method or the 'Added' entity state to track the graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate.

protected virtual async Task EditRecordAsync(CreateOrEditPatientDto input)
        {
            Debug.Assert(input.Patient.Id != null, "input.Patient.Id should be set.");
            var patient = input.Patient.MapTo<Models.Patient.Patient>();
            //Make sure some fields not editied in patien object
            var oldPatient = await _patientRepository.GetAsync(patient.Id);

            patient.IsActive = oldPatient.IsActive;
            patient.IsCertified = oldPatient.IsCertified;
            patient.ParentId = oldPatient.ParentId;
            patient.DateEnd = oldPatient.DateEnd;
            
            await _patientRepository.UpdateAsync(patient);  // the error been thrown at this line
            await _unitOfWorkManager.Current.SaveChangesAsync();
            input.User.Name = input.Patient.NameAr;
            input.User.Surname = input.Patient.NameEn;


            Debug.Assert(input.User.Id != null, "input.User.Id should be set.");
            var user = await UserManager.FindByIdAsync(input.User.Id.Value);
            //Update user properties
            input.User.MapTo(user); 
            CheckErrors(await UserManager.UpdateAsync(user));
        }

if i removed these lines it work fine

var oldPatient = await _patientRepository.GetAsync(patient.Id);

            patient.IsActive = oldPatient.IsActive;
            patient.IsCertified = oldPatient.IsCertified;
            patient.ParentId = oldPatient.ParentId;
            patient.DateEnd = oldPatient.DateEnd;

but i need to do this anyway what's wrong with my code as i faced this error many times ?


3 Answer(s)
  • User Avatar
    0
    moustafa created

    actually this issue help me to fix my problem [https://github.com/aspnetboilerplate/aspnetboilerplate/issues/1354])

    but i don't what i'm doing in the previous snippet of code is right or not is there any way to exclude some properties from being mapped or updated what is the good practice for such a cases ? thank you

  • User Avatar
    0
    hikalkan created
    Support Team

    Hi,

    var oldPatient = await _patientRepository.GetAsync(patient.Id);
    

    This adds the patient entity to the context.

    await _patientRepository.UpdateAsync(patient);
    

    This tries to add another patient entity (with same id) to the context.

    First of all, this is related to usage of EF (you will get the same exception in any project with EF, not related to AspNet Zero).

    You have 2 options for best practice:

    1. Remove the unwanted properties from DTO. Thus, they will not be mapped. Optionally, you can configure AutoMapper to ignore these properties. I suggest this approach.

    Then you can get entity from repository and override (map) with the input DTO.

    var patient = await _patientRepository.GetAsync(input.Patient.Id);
    input.Patient.MapTo(patient);
    

    Even no need to call repository.Update method (document: <a class="postlink" href="http://www.aspnetboilerplate.com/Pages/Documents/Unit-Of-Work#DocAutoSaveChanges">http://www.aspnetboilerplate.com/Pages/ ... aveChanges</a>)

    1. If you can not delete these proeprties from DTO; Get entity from repository, set input's propeties from entity and map input to entity.
  • User Avatar
    0
    moustafa created

    Thank you for your advice
    i'll let you know my progress