编辑实体时出错:由于一个或多个外键属性不可为空,因此无法更改关系

时间:2019-01-02 09:00:12

标签: c# entity-framework automapper

我正在使用AutoMapper映射我的应用程序中的模型。添加一个新实体可以正常工作,但是当我尝试更新现有实体时出现此错误:

  

操作失败:由于一个或多个外键属性不可为空,因此无法更改关系。对关系进行更改时,相关的外键属性将设置为空值。如果外键不支持空值,则必须定义新的关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象。

我的控制器:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult RecipeForm(RecipeDto dto, HttpPostedFileBase image)
{
    // validation and upload image file
    var orgRecipe = _context.Recipes
                            .Where(r => r.Id == dto.Id)
                            .Include(i => i.Ingredients)
                            .SingleOrDefault();

    if (orgRecipe != null)
    {
        var recipe = Mapper.Map<RecipeDto, Recipe>(dto, orgRecipe);
        // Uncommenting lines below also doesn't help
        //_context.Set<Recipe>().Attach(recipe);
        //_context.Entry<Recipe>(orgRecipe).State = EntityState.Modified;
    }
    else
    {
        var newRec = Mapper.Map<Recipe>(dto);
        _context.Recipes.Add(newRec);
    }

    _context.SaveChanges();

    return RedirectToAction("Index", "Home");    
}

Automapper配置:

public static class AutomapperConfig
{
    public static void RegisterMappings()
    {
        AutoMapper.Mapper.Initialize(cfg =>
        {
            cfg.AddCollectionMappers();
            cfg.SetGeneratePropertyMaps<GenerateEntityFrameworkPrimaryKeyPropertyMaps<ApplicationDbContext>>();

            cfg.CreateMap<RecipeDto, Recipe>(MemberList.Source)
                .EqualityComparison(((dto, recipe) => dto.Id == recipe.Id));

            cfg.CreateMap<IngredientDto, Ingredient>(MemberList.Source)
                .EqualityComparison(((dto, ingredient) => dto.Id == ingredient.Id));

        });
        Mapper.AssertConfigurationIsValid();
    }
}

型号:

public class Recipe
{
    public int Id { get; set; }

    [Required]
    [StringLength(255)]
    public string Name { get; set; }

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

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

    [StringLength(255)]
    public string ImageFilename { get; set; }

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

    public virtual ICollection<Rating> Ratings { get; set; }
}

public class Ingredient
{
    public int Id { get; set; }

    [StringLength(255)]
    public string Name { get; set; }

    public int RecipeId { get; set; }
}

解决方案中使用的软件包:

AutoMapper
AutoMapper.Collection
AutoMapper.Collection.EntityFramework
AutoMapper.Extensions.ExpressionMapping

-编辑-

这是我的DTO

public class RecipeDto
{
    public int Id { get; set; }

    [Required]
    [StringLength(255)]
    public string Name { get; set; }

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

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

    [StringLength(255)]
    public string ImageFilename { get; set; }

    [Required]
    public virtual List<IngredientDto> Ingredients { get; set; }

    public virtual ICollection<RatingDto> Ratings { get; set; }
}

public class IngredientDto
{
    public int Id { get; set; }

    [StringLength(255)]
    public string Name { get; set; }

    public int RecipeId { get; set; }
}

1 个答案:

答案 0 :(得分:0)

在Recipe类中,必须具有成分信息。RecipeDto类必须具有具有“成分”名称和“成分Dto”类型的属性。