【问题标题】:Duplicate DataType is being created on every Product Creation每次创建产品时都会创建重复的数据类型
【发布时间】:2013-06-18 10:18:55
【问题描述】:

我有一个产品模型,允许用户为其产品定义自己的自定义字段。这是通过有 3 个表/模型来完成的。 Product 模型包含 CustomProductProperty 模型的 IEnumerable 枚举。在每个CustomProductPropertyModel 中都是DataType 模型的外键。这个DataType 模型是用户定义可用字段的地方。

我遇到的问题是,每次用户创建新产品时,都会创建一组新的DataType。如何处理数据以使 CustomProductProperty 指向现有的 DataType 而不是创建新的?

[Table("Product")]
public class Product
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int ProductID { get; set; }
    public int ProductTypeID { get; set; }
    [Display(Name = "Product Name")]
    public string ProductName { get; set; }
    [ForeignKey("ProductTypeID")]
    [Display(Name = "Product Type")]
    public virtual ProductType ProductType { get; set; }
    public virtual ICollection<CustomProductProperty> CustomProperties { get; set; } 
}

[Table("CustomProductProperty")]
public class CustomProductProperty
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int CustomPropertyID { get; set; }

    public int CustomDataTypeID { get; set; }
    [ForeignKey("CustomDataTypeID")]
    public CustomDataType DataType { get; set; }

    public int ProductID { get; set; }
    [ForeignKey("ProductID")]
    public virtual Product Product { get; set; }

    public string PropertyValue { get; set; }
}

[Table("CustomDataType")]
public class CustomDataType
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int CustomTypeID { get; set; }
    public string PropertyName { get; set; }
    public CustomDataTypes DataType { get; set; }
    public int ModuleID { get; set; }
    [ForeignKey("ModuleID")]
    public Module Module { get; set; }
}

在创建表单中,我为DataType.CustomTypeID 包含了一个@Html.HiddenFor(),在调试时,它被包含在内,但是当我添加到我的dbcontext 时,它会创建一个全新的DataType

if (ModelState.IsValid)
    {
        db.Products.Add(productViewModel.Product);
        db.SaveChanges();
        return RedirectToAction("Index");
    }

编辑:创建产品的形式如下。

<table class="basic_info_tbl">
    <tr>
        <th>@Html.LabelFor(model => model.Product.ProductName):</th>
        <td>@Html.TextBoxFor(model => model.Product.ProductName) </td>
        <th>@Html.LabelFor(model => model.Product.ProductType):</th>
        <td>@Html.DropDownListFor(model => model.Product.ProductTypeID, Model.ProductTypes)</td>
        @Html.EditorFor(model => model.Product.CustomProperties)
    </tr>
</table>

使用编辑器模板:

<tr>
        @Html.HiddenFor(model => model.DataType.CustomTypeID)
    <th>@Model.DataType.PropertyName</th>
    <td>@Html.TextBoxFor(model => model.PropertyValue)</td>
</tr>

【问题讨论】:

  • 您的数据类型必须附加到上下文中,否则将创建一个新的。
  • 我该怎么做?
  • 例如:DataType dt = new DataType { CustomTypeID = someDataFromTheModel}; context.Set&lt;DataType&gt;().Attach(dt);。这假定 CustomTypeID 是 DataType 的主键。
  • 如果我有一个包含 DataType 的模型的 ICollection&lt;&gt; 集合,我是否只在 foreach 循环中运行它?
  • 是的,你必须这样做,或者你可以尝试附加一个包含 ICollection 的实体图。

标签: c# asp.net entity-framework asp.net-mvc-4


【解决方案1】:

来自 Lerman & Miller 的书DbContext

添加图的根会导致图中的每个实体 要在上下文中注册为新实体的图。这种行为是一样的 如果您使用DbSet.Add 或将实体的State 属性更改为Added。一旦所有 实体由状态管理器跟踪,您可以然后按自己的方式处理图表, 为每个实体指定正确的状态。

(我的重点)

所以在db.Products.Add(productViewModel.Product) 之后,对象图中的CustomDataType 对象也是Added

Add() 之后,您应该循环遍历对象图

foreach (var dt in productViewModel.Product.CustomProperties
                                   .Select(x => x.DataType).ToList())
{
    Entry(dt).State = EntityState.Unchanged;
}

【讨论】:

  • 当我尝试实现此An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key. 时出现错误,做一些研究表明我需要检查它是否已经被跟踪并使用EntityState.Modified 如果是?但我不希望这些数据意外更改。
  • 你从哪里得到异常?这应该是可能的。为了简洁起见,您是否还有更多的事情发生了?
  • 我在Entry(dt).State = EntityState.Unchanged; 得到了异常,我没有遗漏任何其他内容。它基本上是视图中的这 3 个模型。
  • 我添加了表单以防万一。
  • 这表明您在更改状态之前以某种方式加载了CustomDataTypes。
猜你喜欢
  • 1970-01-01
  • 2013-04-01
  • 2020-07-03
  • 2018-06-25
  • 1970-01-01
  • 2017-01-03
  • 2016-04-01
  • 2011-03-22
  • 2018-12-09
相关资源
最近更新 更多