我正在尝试使用Entity Framework代码优先将下面的对象保存到数据库中,数据库已正确创建,但是当调用SaveChanges();
时,它会出现在异常之下。
保存或接受更改失败,因为多个“ ConditionalOptions”类型的实体具有相同的主键值。确保显式设置的主键值是唯一的。确保在数据库和实体框架模型中正确配置了数据库生成的主键。将实体设计器用于数据库优先/模型优先配置。使用“ HasDatabaseGeneratedOption”流利的API或“ DatabaseGeneratedAttribute”进行代码优先配置。
有人可以带我去正确的方向吗?
我有这个JSON:
{
"components": [
{
"label": "Text Field",
"key": "1",
"conditional": {
"show": "",
"when": "",
"json": ""
}
},
{
"label": "Columns",
"columns": [
{
"ParentComponentKey":"4",
"components": [
{
"label": "Text Field",
"key": "5",
"conditional": {
"show": "",
"when": "",
"json": ""
}
}
],
"Id":"1"
}
],
"key": "4",
"conditional": {
"show": "",
"when": "",
"json": ""
}
},
{
"type": "button",
"label": "Submit",
"key": "7",
"disableOnInvalid": true,
"theme": "primary",
"input": true,
"tableView": true
}
]
}
我创建了这些模型类以将数据映射到对象中
public class Form
{
public Form()
{
this.Components = new HashSet<ComponentOptions>();
}
[Key]
public int Id { get; set; }
public string title { get; set; }
public virtual ICollection<ComponentOptions> Components { get; set;}
}
public class ComponentOptions
{
[Key, Column(Order = 0)]
public int FormId { get; set; }
[Key, Column(Order = 1)]
public int Key { get; set; }
public string label { get; set; }
public virtual ConditionalOptions conditional { get; set; }
public virtual ICollection<ColumnOptions> columns { get; set; }
[ForeignKey("FormId")]
public virtual Form Form { get; set; }
}
public class ConditionalOptions
{
[Key, ForeignKey("ComponentOptions"), Column(Order = 0)]
public Int64 FormId { get; set; }
[Key, ForeignKey("ComponentOptions"), Column(Order = 1)]
public int Key { get; set; }
public string show { get; set; }
public string when { get; set; }
public string eq { get; set; }
public virtual ComponentOptions ComponentOptions { get; set; }
}
public class ColumnOptions
{
//[ForeignKey("FormId,Key")]
//public virtual ComponentOptions ComponentOption { get; set; }
public ColumnOptions()
{
this.components = new HashSet<ComponentOptions>();
}
[Key, Column(Order = 0)]
public Int64 FormId { get; set; }
[Key, Column(Order = 1)]
public int ParentComponentKey { get; set; }
[Key, Column(Order = 2)]
public int Id { get; set; }
public string Key { get; set; }
public int width { get; set; }
public int offset { get; set; }
public int push { get; set; }
public int pull { get; set; }
public virtual ICollection<ComponentOptions> components { get; set; }
[ForeignKey("FormId")]
public virtual Form Form { get; set; }
}
public class EntitesContext : DbContext
{
public EntitesContext() : base("name=FBEntities")
{
Database.SetInitializer<EntitesContext>(new System.Data.Entity.CreateDatabaseIfNotExists<EntitesContext>());
}
public IDbSet<Form> FormDataSet { get; set; }
public IDbSet<ColumnOptions> ColumnOptionsDataSet { get; set; }
public IDbSet<ComponentOptions> ComponentOptionsDataSet { get; set; }
public IDbSet<ConditionalOptions> ConditionalOptionsDataSet { get; set;}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
modelBuilder.Entity<ComponentOptions>()
.HasMany(s => s.columns)
.WithMany(c => c.components)
.Map(cs =>
{
cs.MapLeftKey("ComponentFormId", "ComponentKey");
cs.MapRightKey("ColumnFormId", "ColumnComponentKey", "ColumnId");
cs.ToTable("ComponentColumn");
});
}
}
答案 0 :(得分:0)
问题在ForeignKey
模型类中的ConditionalOptions
配置中。您已经将相同的导航属性指向了两个外键,这两个外键也是您的复合主键。
由于ComponentOptions
的主键是复合键,因此您的ConditionalOptions
配置应在以下方面有些棘手,以保持它们之间的one-to-one
关系。
public class ConditionalOptions
{
[Key]
public Int64 ConditionalOptionsId { get; set; }
public string show { get; set; }
public string when { get; set; }
public string eq { get; set; }
public virtual ComponentOptions ComponentOptions { get; set; }
}
然后使用Fluent API,如下所示:
modelBuilder.Entity<ConditionalOptions>()
.HasRequired(co => co.ComponentOptions)
.WithOptional(c => c.conditional)
.Map(co => co.MapKey(new []{ "FormId", "Key" }));