Base solution for your next web application
Open Closed

referenced tables won't update #1156


User avatar
0
virtual created

Hello. I am trying to update my records but only the table I am updating with UpdateAsync will update. I use AutoMapper to map to DTOs, the fields seem to map alright. The insertion is working and I can see data in all three tables. So, I am trying to update my recipeRepository, but only the recipe table is being updated entity classes:

public class Recipe : Entity, ISoftDelete, IHasCreationTime, IHasModificationTime
    {
        [Key]
        [Column("id")]
        public override int Id { get; set; }

        public string recipe_name { get; set; }
        public string recipe_dish { get; set; }
        public Nullable<float> recipe_cooking_time { get; set; }
        public Nullable<float> recipe_preparation_time { get; set; }
        public string recipe_author { get; set; }
        public string recipe_description { get; set; }
        public string recipe_image { get; set; }

        public virtual ICollection<Ingredient> Ingredients { get; set; }

        public bool IsDeleted { get; set; }
        public DateTime CreationTime { get; set; }
        public DateTime? LastModificationTime { get; set; }
    }
}
public class Product : Entity
    {
        [Key]
        [Column("id")]
        public override int Id { get; set; }
        public string product_name { get; set; }

        public virtual ICollection<Ingredient> Ingredients { get; set; }
    }
public class Ingredient : Entity
    {
        [Key]
        [Column("id")]
        public override int Id { get; set; }
        public Nullable<float> ingredient_quantity { get; set; }
        public string ingredient_unit { get; set; }
        public string ingredient_notes { get; set; }
        [Required]
        public int ingredient_recipe_id { get; set; }
        [Required]
        public int ingredient_product_id { get; set; }
        [ForeignKey("ingredient_product_id")]
        public virtual Product Product { get; set; }

        [ForeignKey("ingredient_recipe_id")]
        public virtual Recipe Recipe { get; set; }
    }
}

I am using mysql provider, maybe it's the provider's fault?


3 Answer(s)
  • User Avatar
    0
    virtual created

    ok, so I tried to update the tables like this:

    public async Task InsertOrUpdateRecipe(GetRecipeInput input)
            {
                try
                {
    
                    if (input != null && input.Id != 0)
                    {
                        var recipe = await _recipeRepository.GetAsync(input.Id);
                        var mapped = input.MapTo(recipe);
                        
                        await _recipeRepository.UpdateAsync(mapped);
                        _unitOfWorkManager.Current.SaveChanges();
                    }
                    else if (input != null)
                    {
                        await _recipeRepository.InsertAsync(input.MapTo<Recipe>());
                    }
                }
                catch (Exception ex)
                {
                    throw;
                }
            }
    

    And the exception is thrown right after saving changes:

    Exception thrown: 'System.InvalidOperationException' in EntityFramework.dll
    
    Additional information: The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.
    

    Anybody experienced anything like that?

  • User Avatar
    0
    sudmanche created

    I have had a similar issue, it is caused because the Navigation properties lose state when POSTed to the update, so AutoMapper then thinks you have updated the entity to a null value.

    It is a symptom of trying to use AutoMapper to map the DTO back to the entity.

    Check you need the navigation properties, or just the id's, or code the mapping manually, or, define a second DTO without navigation properties, then in the update map the original DTO to the cutdown DTO, then map that DTO to the domain entity (not very pretty, but effective).

    like this...

    if (ModelState.IsValid)
                {
                    var entity = await _entityManager.FindAsync(model.entityDto.Id);
    
                    //map via edit DTO to ignore Navigation Properties
                    var editEntityDto = model.entityDto.MapTo<EntityEditDto>();
                    editEntityDto.MapTo(activity);
    
                    await _activityManager.UpdateAsync(entity);
    
                    return RedirectToAction("Index");
                }
    

    hope that makes sense!

  • User Avatar
    0
    virtual created

    Thank you for replying. I see what you mean, I recently just queried my database to restore references and mapped manually from dtos. I understand that automapper isn't designed to map dtos back to entities. But isn't there a more elegant solution?