添加一个具有1级一对多关系的实体非常简单。
using (var dbCtx = new DbContext())
{
dbCtx.Stuff.Add(myObject);
dbCtx.SaveChanges();
}
但是如何添加具有两个级别的对象?以相同的方式添加它会省略2。数量这意味着Bar对象(在下面的示例中)不会被保存。我做错了什么?
对象图
继承的对象
public class BaseEntity
{
public int Id;
// Omitted properites...
}
public class MyEntity : BaseEntity
{
// Omitted properites...
// Navigation properties
public virtual ICollection<Foo> Foos { get; set; }
}
嵌套对象(1:M)
public class Foo // 1. level
{
public int Id;
public int MyEntityId;
// Omitted properites...
// Navigation properties
public virtual ICollection<Bar> Bars { get; set; }
public virutal MyEntity MyEntity { get; set; }
}
public class Bar // 2. level
{
public int Id;
public int FooId;
// Omitted properites...
// Navigation properties
public virutal Foo Foo { get; set; }
}
使用fluent API进行映射设置
继承的对象
public class BaseEntityMap : EntityTypeConfiguration<BaseEntity>
{
public BaseEntityMap()
{
// Primary Key
this.HasKey(t => t.Id);
// Properties
// Table & Column Mappings
this.ToTable("BaseEntitySet");
this.Property(t => t.Id).HasColumnName("Id");
// ...
}
}
public class MyEntityMap : EntityTypeConfiguration<MyEntity>
{
public MyEntityMap()
{
// Table & Column Mappings
this.ToTable("BaseEntitySet_MyEntities");
}
}
嵌套对象(1:M)
public class FooMap : EntityTypeConfiguration<Foo>
{
public FooMap()
{
// Primary Key
this.HasKey(t => t.Id);
// Table & Column Mappings
this.ToTable("FooSet");
this.Property(t => t.Id).HasColumnName("Id");
this.Property(t => t.MyEntityId).HasColumnName("MyEntity_Id");
// Relationships
this.HasRequired(t => t.MyEntity)
.WithMany(t => t.Foos)
.HasForeignKey(d => d.MyEntityId);
}
}
public class BarMap : EntityTypeConfiguration<Bar>
{
public BarMap()
{
// Primary Key
this.HasKey(t => t.Id);
// Table & Column Mappings
this.ToTable("BarSet");
this.Property(t => t.Id).HasColumnName("Id");
this.Property(t => t.FooId).HasColumnName("Bar_Id");
// Relationships
this.HasRequired(t => t.Foo)
.WithMany(t => t.Bars)
.HasForeignKey(d => d.FooId);
}
}
存储库
public void Add(BaseEntity item)
{
using (var ctx = new DbContext())
{
ctx.BaseEntities.Add(item);
ctx.SaveChanges();
}
}
\想发布我的答案,以防对他人有帮助,这样专家就可以把它撕成碎片,发布真正的答案。对我来说,它并不是突然开始工作的:)
如果我正确理解你的对象图,它是MyEntity有Foos,它有Bars。我有一个类似的结构,但当调用"SaveChanges"时,会抛出一个DbUpdateException,并显示
"多个实体可能具有相同的主键。"
以下是我如何让它为我工作的:
步骤1:是否将Id属性从int更改为int?并将它们初始化为null。对我来说,这是一个比普通整数更准确的模型。当一个实体是新的时,ID实际上是"未定义或未知"。0是一个已定义的数字,由于某些原因,即使在添加记录时,EF也会遇到ID相同的问题。
public class BaseEntity
{
public BaseEntity()
{
this.Id = null;
}
public int? Id;
// Omitted properites...
}
public class Foo
{
public Foo()
{
this.Id = null;
}
public int? Id;
}
public class Bar
{
public Bar()
{
this.Id = null;
}
public int? Id;
}
步骤2:将"DatabaseGeneratedOption.Identity"标志添加到映射中的Id属性中。我相信这可以防止在实体被添加到数据上下文的情况下"需要"它。
public class BaseEntityMap : EntityTypeConfiguration<BaseEntity>
{
public BaseEntityMap()
{
// Primary Key
this.HasKey(t => t.Id);
// Properties
// Table & Column Mappings
this.ToTable("BaseEntitySet");
this.Property(t => t.Id).HasColumnName("Id")
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
// ...
}
}
public class FooMap : EntityTypeConfiguration<Foo>
{
public FooMap()
{
// Primary Key
this.HasKey(t => t.Id);
// Table & Column Mappings
this.ToTable("FooSet");
this.Property(t => t.Id).HasColumnName("Id")
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
this.Property(t => t.MyEntityId).HasColumnName("MyEntity_Id");
// Relationships
this.HasRequired(t => t.MyEntity)
.WithMany(t => t.Foos)
.HasForeignKey(d => d.MyEntityId);
}
}
public class BarMap : EntityTypeConfiguration<Bar>
{
public BarMap()
{
// Primary Key
this.HasKey(t => t.Id);
// Table & Column Mappings
this.ToTable("BarSet");
this.Property(t => t.Id).HasColumnName("Id")
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
this.Property(t => t.FooId).HasColumnName("Bar_Id");
// Relationships
this.HasRequired(t => t.Foo)
.WithMany(t => t.Bars)
.HasForeignKey(d => d.FooId);
}
}