Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Entity framework MVC3中的实体框架:如何插入带有外键的模型?_Entity Framework_Asp.net Mvc 3_Insert_Foreign Key Relationship - Fatal编程技术网

Entity framework MVC3中的实体框架:如何插入带有外键的模型?

Entity framework MVC3中的实体框架:如何插入带有外键的模型?,entity-framework,asp.net-mvc-3,insert,foreign-key-relationship,Entity Framework,Asp.net Mvc 3,Insert,Foreign Key Relationship,我有一个产品模型,其中包含ProductCategory记录的外键,如下所示 public class ProductModel : IProductModel { public int ProductID { get; set; } public string ProductName { get; set; } public string ProductDescription { get; set; } public string ProductImagePat

我有一个产品模型,其中包含ProductCategory记录的外键,如下所示

public class ProductModel : IProductModel
{
    public int ProductID { get; set; }
    public string ProductName { get; set; }
    public string ProductDescription { get; set; }
    public string ProductImagePath { get; set; }
    public decimal? PricePerMonth { get; set; }
    public bool ProductActive { get; set; }
    public ProductCategory ProductCategory { get; set; }
}
出于某种原因,每次创建新产品时,都会创建一个新的ProductCategory,其中数据库中的所有值都设置为NULL,ProductCategoryID字段除外,该字段是自动生成的

在我的创建视图中,我有一个表单,其中包含一个用ProductCategories填充的下拉列表。提交表单后,将调用创建(产品)操作,并创建新产品。此时,还创建了新的ProductCategory,这是我不想要的行为

我的创建(产品)操作如下所示:

    //
    // POST: /Product/Create
    [HttpPost]
    public ActionResult Create(Product product)
    {
        int productCategoryID = product.ProductCategory.ProductCategoryID;
        product.ProductCategoryID = productCategoryID;
        _productService.InsertProduct(product);
    }
<td valign="top"><label>Bank:</label> <span class="red">*</span></td>
<td>
   @Html.DropDownListFor(x => x.BankId, new SelectList(Model.Banks, "Id", "Name", Model.BankId), "-- Select --")<br>
   @Html.ValidationMessageFor(x => x.BankId)
</td>
。。。我的InsertProduct方法如下所示

    public void InsertProduct(Product product)
    {
        Db.Products.AddObject(product);
        Save();
    }
为什么这段代码每次都要创建一个新的ProductCategory

编辑:添加表格定义,回应给出的答案,whcih询问更多信息:

TABLE Product (
ProductID INT PRIMARY KEY IDENTITY(1,1),
ProductCategoryID INT, -- FK to ProductCategory 
ProductName NVARCHAR(255),
ProductDescription NVARCHAR(MAX),
ProductImagePath NVARCHAR(1024),
PricePerMonth DECIMAL(7,2), -- ex 11111.11
ProductActive BIT NOT NULL DEFAULT(1)
)

TABLE ProductCategory (
ProductCategoryID INT PRIMARY KEY IDENTITY(1,1),
ProductCategoryName NVARCHAR(255),
ProductCategoryDescription NVARCHAR(MAX),
ProductCategoryActive BIT NOT NULL DEFAULT(1)
)
编辑2:

我仍然不明白确切的原因,但通过对我的创建(产品)操作进行以下更改,我能够解决这个问题:

编辑3:


我仍在努力想这些,但是。。。我发现这个问题与Product类的ProductCategory成员有关。据我所知,每次提交表单时,ModelBinding都会自动使用新的ProductCategory填充该属性。通过显式设置Product.ProductCategory=null,我可以始终避免我在这里遇到的问题

已创建产品类别,因为您正在为新产品对象设置ProductCategoryID

我想知道你们为什么这样设置产品类别?这个分类id来自哪里

无论如何,如果您使用的是实体框架,您必须确保在SQL server中具有正确的关系(例如一对一或一对多)。实体框架中的一些意外行为与sql server中糟糕的数据库设计有关


无论如何,如果这不能帮助你给我你确切的表映射和关系,写下你想要实现的更精确的内容

在您的
Create
操作中,
productCategoryID
分配后的值是多少?它是从表单上的下拉列表中选择的值,还是新值

如果已定义从ProductCategory表中的主键到Product表中的外键的外键关系,则每次使用ProductCategoryID值保存产品时,ProductCategoryID值必须存在于ProductCategory表中

因此,如果要使用ProductCategory表中不存在的ProductCategoryID值保存产品,则必须将该记录插入ProductCategory表中,才能将该记录插入Product表中

另外,通常您的
Create
操作应该从
Create
视图接受
ProductModel
对象。这是您的页面数据模型,您可以从中提取从EF上下文(“实体”对象)创建
产品
实体所需的值,然后保存
产品
实体


我不太清楚您的
产品
产品模型
类的区别。

根据您的描述,问题最有可能出现在您创建下拉列表的代码中

public class EditGrantApplicationViewModel
{
   // Other properties

   public int BankId { get; set; }
   public List<Bank> Banks { get; set; }
}
在控制器中,创建ProductCategory表的
IEnumerable
,并将其传递给ViewBag,例如
ViewBag.ProductCategories
。然后,在您的视图中,使用以下下拉列表:

@Html.DropDownListFor(model => model.ProductCategoryId, (IEnumerable<SelectListItem>)ViewBag.ProductCategories)
@Html.DropDownListFor(model=>model.ProductCategoryId,(IEnumerable)ViewBag.ProductCategories)

然后,在[HttpPost]创建控制器操作中,ProductCategoryId将被正确填充。

@campbelt:不确定为什么会发生这种情况。我就是这样做的。我没有将域对象传递给视图,而是传递了一个名为
EditGrantApplicationViewModel
的视图模型。在我的场景中,我有一个拨款申请表。在此表单上,用户可以从下拉列表中选择银行。下面是我的局部视图模型,包含银行下拉列表的详细信息

public class EditGrantApplicationViewModel
{
   // Other properties

   public int BankId { get; set; }
   public List<Bank> Banks { get; set; }
}
部分GrantApplication对象:

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

   public int BankId { get; set; }
}

映射将从下拉列表中填充GrantApplication对象(已选中)中的BankId属性,这是将添加到GrantApplication表中的列中的内容。

我对您的问题很好奇,因此我从一位著名的MVC作者和培训师那里得到了一些提示,并得出以下结论。关键概念可在中找到

MVC模型绑定过程将视图中的表单数据绑定到传递给创建操作的模型。它在表单数据中找到要绑定到Product和ProductCategory对象的适当值,并执行模型绑定

您案例中的问题是实体框架不知道对象,因为您在EF上下文之外自己创建了Product和ProductCategory对象,而不是从EF上下文创建实体。在您的例子中,您将EF4.1与DbContext一起使用,但这也将通过不同的方法应用于EF4.0与ObjectContext

您的新产品对象在EF上下文或数据库中不存在——您尚未添加它——但您的ProductCategory存在。您需要将挂起新产品对象的ProductCategory对象映射到EF实体中的现有ProductCategory。为此,您可以通过主键(ProductCategoryId)查找现有ProductCategory,然后将其分配给product.ProductCategory,或者将自由浮动的ProductCategory对象“附加”到实体。您将其传递给ProductCategory对象,它的作用与查找现有实体的作用基本相同——它是l
public class GrantApplication
{
   public int Id { get; set; }

   public int BankId { get; set; }
}
public ActionResult Create(Product product)
{
    // find an attached entity based on primary key
    var productCat = 
        Db.ProductCategories.Find(product.ProductCategory.ProductCategoryId); 
    product.ProductCategoryId = productCat.ProductCategoryId;
    product.ProductCategory = productCat;
    _productService.InsertProduct(product);
}
public ActionResult Create(Product product)
{
    // attach an entity - EF will find the entity to attach using the entity's primary key
    Db.ProductCategories.Attach(product.ProductCategory); 
    product.ProductCategoryId = product.ProductCategory.ProductCategoryId;
    _productService.InsertProduct(product);
}
public ActionResult Create(Product product)
{
    product.ProductCategoryId = product.ProductCategory.ProductCategoryId;
    product.ProductCategory = null;
    _productService.InsertProduct(product);
}