Asp.net mvc 不确定如何使用具有多对多关系的实体框架将项插入数据库

Asp.net mvc 不确定如何使用具有多对多关系的实体框架将项插入数据库,asp.net-mvc,entity-framework,Asp.net Mvc,Entity Framework,我正在尝试将一个产品插入到我的数据库中,其中包含一个关联的类别。一个产品可以属于多个类别,显然一个类别可以有多个产品。当我插入时,我确信我的控制器方法中缺少了一些东西,但我不确定它是什么。我有一个名为ProductCategory的桥接表,其中只有一个ProductID和一个CategoryID。当我插入时,该表没有填充 以下是执行插入的控制器方法: [HttpPost] [ValidateAntiForgeryToken] public ActionResult EditPr

我正在尝试将一个产品插入到我的数据库中,其中包含一个关联的类别。一个产品可以属于多个类别,显然一个类别可以有多个产品。当我插入时,我确信我的控制器方法中缺少了一些东西,但我不确定它是什么。我有一个名为ProductCategory的桥接表,其中只有一个ProductID和一个CategoryID。当我插入时,该表没有填充

以下是执行插入的控制器方法:

 [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult EditProduct([Bind(Include = "ID,itemNumber,product,description,active,PDFName,imageName,SelectedCategories")] ProductModel model)
    {
        if (ModelState.IsValid)
        {
            using (var context = new ProductContext())
            {
                context.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);
                if (model.ID == 0)
                {
                    // Since it didn't have a ProductID, we assume this
                    // is a new Product
                    if (model.description == null || model.description.Trim() == "")
                    {
                        model.description = "Our Famous " + model.product;
                    }
                    if (model.imageName == null || model.imageName.Trim() == "")
                    {
                        model.imageName = model.itemNumber + ".jpg";
                    }
                    if (model.PDFName == null || model.PDFName.Trim() == "")
                    {
                        model.PDFName = model.itemNumber + ".pdf";
                    }
                    Session["dropdownID"] = model.ID;

                    // I think I probably need some additional code here...

                    context.Products.Add(model);
                }
                else
                {
                    // Since EF doesn't know about this product (it was instantiated by
                    // the ModelBinder and not EF itself, we need to tell EF that the
                    // object exists and that it is a modified copy of an existing row
                    context.Entry(model).State = EntityState.Modified;
                }
                context.SaveChanges();
                return RedirectToAction("ControlPanel");
            }
        }
        return View(model);
    }
以及我的产品型号:

public class ProductModel
{
    public int ID { get; set; }

    [Required(ErrorMessage = "Required")]
    [Index("ItemNumber", 1, IsUnique = true)]
    [Display(Name = "Item #")]
    public int itemNumber { get; set; }

    [Required(ErrorMessage = "Required")]
    [Display(Name = "Product")]
    [MaxLength(50)]
    public String product { get; set; }

    [Display(Name = "Description")]
    [MaxLength(500)]
    public String description { get; set; }

    [DefaultValue(true)]
    [Display(Name = "Active?")]
    public bool active { get; set; }

    [Display(Name = "Image Name")]
    public String imageName { get; set; }

    [Display(Name = "PDF Name")]
    public String PDFName { get; set; }

    [Display(Name = "Category(s)")]
    public virtual ICollection<CategoryModel> ProductCategories { get; set; }

    public int[] SelectedCategories { get; set; }

    public IEnumerable<SelectListItem> CategorySelectList { get; set; }

    //public ICollection<CategoryModel> CategoryList { get; set; }

    public virtual BrochureModel Brochure { get; set; }

    public IEnumerable<SelectListItem> BrochureList { get; set; }

    [Display(Name = "Category(s)")]
    public String CategoryList { get; set; }

    public static IEnumerable<SelectListItem> getCategories(int id = 0)
    {
        using (var db = new ProductContext())
        {
            List<SelectListItem> list = new List<SelectListItem>();
            var categories = db.Categories.ToList();
            foreach (var cat in categories)
            {
                SelectListItem sli = new SelectListItem { Value = cat.ID.ToString(), Text = cat.categoryName };

                //if (id > 0 && cat.ID == id)
                //{
                //    sli.Selected = true;
                //}
                list.Add(sli);
            }
            return list;
        }

    }

    public ProductModel()
    {
        active = true;
    }

}
公共类产品模型
{
公共int ID{get;set;}
[必需(ErrorMessage=“必需”)]
[索引(“ItemNumber”,1,IsUnique=true)]
[显示(Name=“Item#”)]
公共int itemNumber{get;set;}
[必需(ErrorMessage=“必需”)]
[显示(Name=“产品”)]
[MaxLength(50)]
公共字符串乘积{get;set;}
[显示(Name=“Description”)]
[最大长度(500)]
公共字符串说明{get;set;}
[默认值(真)]
[显示(Name=“活动?”)]
公共bool活动{get;set;}
[显示(名称=“图像名称”)]
公共字符串imageName{get;set;}
[显示(Name=“PDF Name”)]
公共字符串PDFName{get;set;}
[显示(Name=“类别)”]
公共虚拟ICollection ProductCategories{get;set;}
public int[]SelectedCategories{get;set;}
公共IEnumerable CategorySelectList{get;set;}
//公共ICollection类别列表{get;set;}
公共虚拟手册模型手册{get;set;}
公共IEnumerable小册子列表{get;set;}
[显示(Name=“类别)”]
公共字符串类别列表{get;set;}
公共静态IEnumerable getCategories(int id=0)
{
使用(var db=new ProductContext())
{
列表=新列表();
var categories=db.categories.ToList();
foreach(类别中的var cat)
{
SelectListItem sli=new SelectListItem{Value=cat.ID.ToString(),Text=cat.categoryName};
//如果(id>0&&cat.id==id)
//{
//sli.Selected=true;
//}
列表。添加(sli);
}
退货清单;
}
}
公共产品模型()
{
主动=真;
}
}
和我的分类模型:

public class CategoryModel
{
    public int ID { get; set; }

    [Required(ErrorMessage = "Required")]
    [Display(Name = "Category Name")]
    [MaxLength(50)]
    public String categoryName { get; set; }

    [MaxLength(50)]
    public String categoryDBName { get; set; }

    [DefaultValue(true)]
    [Display(Name = "Active?")]
    public bool isActive { get; set; }

    //public virtual ICollection<ProductCategory> ProductCategories { get; set; }

    public virtual ICollection<ProductModel> Products { get; set; }


}
公共类类别模型
{
公共int ID{get;set;}
[必需(ErrorMessage=“必需”)]
[显示(名称=“类别名称”)]
[MaxLength(50)]
公共字符串categoryName{get;set;}
[MaxLength(50)]
公共字符串categoryDBName{get;set;}
[默认值(真)]
[显示(Name=“活动?”)]
公共bool isActive{get;set;}
//公共虚拟ICollection ProductCategories{get;set;}
公共虚拟ICollection产品{get;set;}
}
以下是我的产品背景:

public class ProductContext : DbContext
{

    public ProductContext()
        : base("DefaultConnection")
    {
        Database.SetInitializer<ProductContext>(new CreateDatabaseIfNotExists<ProductContext>());
    }

    public DbSet<CategoryModel> Categories { get; set; }
    public DbSet<ProductModel> Products { get; set; }
    public DbSet<BrochureModel> Brochures { get; set; }


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

        modelBuilder.Entity<CategoryModel>().ToTable("Categories");
        modelBuilder.Entity<ProductModel>().ToTable("Products");
        modelBuilder.Entity<BrochureModel>().ToTable("Brochures");

        modelBuilder.Entity<ProductModel>()
        .HasMany(p => p.ProductCategories)
        .WithMany(p => p.Products)
        .Map(m =>
        {
            m.ToTable("ProductCategory");
            m.MapLeftKey("ProductID");
            m.MapRightKey("CategoryID");
        });

        //modelBuilder.Entity<CategoryModel>()
        //.HasMany(c => c.ProductCategories)
        //.WithRequired()
        //.HasForeignKey(c => c.CategoryID);

    }

    public System.Data.Entity.DbSet<newBestPlay.Models.RegisterViewModel> RegisterViewModels { get; set; }
}
公共类ProductContext:DbContext
{
公共产品上下文()
:base(“默认连接”)
{
SetInitializer(新的CreateDatabaseIfNotExists());
}
公共数据库集类别{get;set;}
公共数据库集产品{get;set;}
公共数据库集手册{get;set;}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove();
//modelBuilder.Conventions.Remove();
//modelBuilder.Conventions.Remove();
modelBuilder.Entity().ToTable(“类别”);
modelBuilder.Entity().ToTable(“产品”);
modelBuilder.Entity().ToTable(“手册”);
modelBuilder.Entity()
.HasMany(p=>p.ProductCategories)
.有许多(p=>p.产品)
.Map(m=>
{
m、 ToTable(“产品类别”);
m、 MapLeftKey(“ProductID”);
m、 MapRightKey(“类别ID”);
});
//modelBuilder.Entity()
//.HasMany(c=>c.ProductCategories)
//.WithRequired()
//.HasForeignKey(c=>c.CategoryID);
}
public System.Data.Entity.DbSet RegisterViewModels{get;set;}
}

如果需要其他代码或更多信息,请告诉我。

您从未使用您的
所选类别
数组执行任何操作。您需要使用它从数据库中提取
CategoryModel
实例,然后将这些实例与产品关联起来

context.Categories.Where(c => model.SelectedCategories.Contains(c.ID)).ToList()
    .ForEach(c => model.ProductCategories.Add(c));

...

context.SaveChanges();
更新

我可以问一下如何列出我认为每个产品的类别吗

这是一个很复杂的问题,因为它很大程度上取决于你想要获得什么样的体验。一般来说,对于任何集合,您都需要迭代该集合中的项,然后为每个项呈现一些HTML。你可以用很多不同的方法来做,这就是为什么我不能给你一个“正确”的答案。但是,为了给您一个想法,而不是让您完全没有代码,这里有一个非常基本的方法来列出每个类别的名称:

@string.Join(", ", Model.ProductCategories.Select(c => c.categoryName))

在添加之前,model.Id是否从会话变量中被分配了正确的值?model.Id是否为0进入“添加”,这在插入新产品时是真的?Id是否是表上的主键?如果是,表中是否已经存储了具有该ID的项?该ID是主ID,但它是自动递增的,因此每次添加产品时,它都会增加一个。正在将产品正确添加到Products表中。它只是没有正确链接到类别。您是否先使用代码设置实体?如果是这样的话,你能发布你的DB上下文类吗?非常好用!我可以问一下如何列出我认为每个产品的类别吗?