【问题标题】:How do I insert autogenerated IDs into association table?如何将自动生成的 ID 插入关联表?
【发布时间】:2016-03-04 18:21:23
【问题描述】:

我正在尝试编写一个从各种烹饪网站上抓取食谱和配料信息的应用程序。它几乎可以按照我想要的方式工作,因为我可以成功地将食谱插入到食谱表中,并将成分插入到成分表中,但是我无法填充关联表。

我的大部分项目都关注this tutorial,但它没有演示如何插入关联表。

我只为 Recipe 创建了一个控制器,其中 Create 函数接受您想要的食谱的 URL。我不想直接操作成分表中的数据,所以我没有为它创建控制器。

我创建了三个模型类:Recipe、Ingredient 和关联表 RecipeIngredient。 Recipe 和 RecipeIngredient 之间存在一对多的关系,以及 Ingredient 和 RecipeIngredient 之间的一对多关系。

这些是我的模型:

public class Recipe
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string URL { get; set; }
    public DateTime DateTimeCreated { get; set; }

    public virtual ICollection<RecipeIngredient> RecipeIngredients { get; set; }
}

public class Ingredient
{
    public int ID { get; set; }
    public string Name { get; set; }
    public DateTime DateTimeCreated { get; set; }

    public virtual ICollection<RecipeIngredient> RecipeIngredients { get; set; }
}

public class RecipeIngredient
{
    public int ID { get; set; }
    public int RecipeID { get; set; }
    public int IngredientID { get; set; }
    public DateTime DateTimeCreated { get; set; }

    public virtual Recipe Recipe { get; set; }
    public virtual Ingredient Ingredient { get; set; }
}

这是我的 DbContext:

public class RecipeListContext : DbContext
{
    public RecipeListContext() : base("RecipeListContext")
    {
    }

    public DbSet<Recipe> Recipes { get; set; }
    public DbSet<RecipeIngredient> RecipeIngredients { get; set; }
    public DbSet<Ingredient> Ingredients { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    }
}

这是来自我的控制器的相关代码:

public class RecipesController : Controller
{
    private RecipeListContext db = new RecipeListContext();

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create([Bind(Include = "URL")] Recipe recipe)
    {
        if (ModelState.IsValid)
        {
            Ingredient ingredient = new Ingredient();
            RecipeIngredient recipeIngredient = new RecipeIngredient();

            var htmlWeb = new HtmlWeb();
            var document = htmlWeb.Load(recipe.URL);

            //This is the route to the recipe and ingredients for 
            //allrecipes.com
            var recipeName = document.DocumentNode.SelectNodes("//h1[@class='recipe-summary__h1']");
            var ingredients = document.DocumentNode.SelectNodes("//span[@itemprop='ingredients']");

            //I populate the Name and DateTimeCreated fields for Recipe here
            recipe.Name = recipeName[0].InnerText;
            recipe.DateTimeCreated = DateTime.Now;

            db.Recipes.Add(recipe);
            db.SaveChanges();

            for (var i = 0; i < ingredients.Count; i++)
            {
                ingredient.Name = ingredients[i].InnerText;
                ingredient.DateTimeCreated = DateTime.Now;
                db.Ingredients.Add(ingredient);
                db.SaveChanges();

                //Here I tried to populate the RecipeIngredient object with 
                //the ID from the Ingredient object, but since that ID gets 
                //created in the database upon insertion, ingredient.ID is 
                //just null. I'm not sure how to access this ID in order to 
                //insert it into RecipeIngredient and I'm not even sure if 
                //this is the right (or best) approach to this problem.

                //recipeIngredient.RecipeID = recipe.ID;
                //recipeIngredient.IngredientID = ingredient.ID;
                //db.RecipeIngredients.Add(recipeIngredient);
                //db.SaveChanges();
            }

            return RedirectToAction("Index");
        }

        return View(recipe);
    }

实体框架中是否有一些函数允许我使用从插入到两个主表中创建的自动生成的 ID 填充关联表?还是有其他解决方案?

编辑: 三个问题阻止了我的应用程序按预期工作。

  1. 我需要取消注释将成分.ID 和配方.ID 分配给 recipeIngredient 外键的代码。

  2. 我需要在 for 循环内实例化配方和成分对象,以便它们在 for 循环的每次传递开始时重新初始化。我在没有重新初始化它们的情况下收到引用完整性错误。

  3. 我需要在 recipeIngredients 中填充 DateTimeCreated 字段。我忘记这样做了,这导致数据库中出现数据类型不匹配错误,因为空值转换为 01/01/0001 或类似的东西,超出了 DateTime 支持的日期范围。

【问题讨论】:

    标签: asp.net-mvc-5 ef-code-first entity-framework-6


    【解决方案1】:

    我相信 EF 应该用身份更新你的实体对象:

    试试这个

    db.Recipes.Add(recipe);
    db.SaveChanges();
    int newPK = recipe.ID;
    

    【讨论】:

    • 感谢您的帮助!这最终成为问题的一部分。在我的程序运行之前,我发现还有两个问题需要解决。我将我的解决方案添加到 cmets。
    【解决方案2】:

    三个问题阻止了我的应用程序按预期工作。

    1. 我需要取消注释将成分 ID 和配方 ID 分配给 recipeIngredient 外键的代码。

    2. 我需要在 for 循环内实例化配方和成分对象,以便它们在 for 循环的每次传递开始时重新初始化。我在没有重新初始化它们的情况下收到了参照完整性错误。

    3. 填充了 RecipeIngredients 中的 DateTimeCreated 字段,因为我之前忘记这样做了。

    我的更新和工作代码如下:

        public ActionResult Create([Bind(Include = "URL")] Recipe recipe)
        {
            if (ModelState.IsValid)
            {
                var htmlWeb = new HtmlWeb();
                var document = htmlWeb.Load(recipe.URL);
    
                var recipeName = document.DocumentNode.SelectNodes("//h1[@class='recipe-summary__h1']");
                var ingredients = document.DocumentNode.SelectNodes("//span[@itemprop='ingredients']");
    
                recipe.Name = recipeName[0].InnerText;
                recipe.DateTimeCreated = DateTime.Now;
    
                db.Recipes.Add(recipe);
                db.SaveChanges();
    
                for (var i = 0; i < ingredients.Count; i++)
                {
                    //Moved these next two lines into the for loop
                    Ingredient ingredient = new Ingredient();
                    RecipeIngredient recipeIngredient = new RecipeIngredient();
    
                    ingredient.Name = ingredients[i].InnerText;
                    ingredient.DateTimeCreated = DateTime.Now;
                    db.Ingredients.Add(ingredient);
                    db.SaveChanges();
    
                    //uncommented this code
                    recipeIngredient.RecipeID = recipe.ID;
                    recipeIngredient.IngredientID = ingredient.ID;
                    //populated the DateTimeCreated field as I had forgotten
                    //to do so already
                    recipeIngredient.DateTimeCreated = DateTime.Now;
                    db.RecipeIngredients.Add(recipeIngredient);
                    db.SaveChanges();
                }
    
                return RedirectToAction("Index");
            }
    
            return View(recipe);
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-10
      • 1970-01-01
      • 1970-01-01
      • 2016-10-22
      • 2020-04-03
      • 2011-04-03
      相关资源
      最近更新 更多