我有一个使用实体框架的ASP.NET MVC应用程序。我使用SQL Server 2008 R2数据库的数据库优先(代码)方法开发了2个模型。一个模型本质上是父模型,另一个模型是子模型,其中包含指向父模型的数据库生成列的外键。
伪代码:
CREATE TABLE PARENT
(
ROWID BIGINT IDENTITY(1,1) NOT NULL,
VALUE NVARCHAR(255) NOT NULL,
PRIMARY KEY(ROWID)
);
CREATE TABLE CHILD
(
ROWID BIGINT IDENTITY(1,1) NOT NULL,
PARENT_ROWID BIGINT NOT NULL,
VALUE NVARCHAR(255) NOT NULL,
PRIMARY KEY(ROWID),
FOREIGN KEY(PARENT_ROWID) REFERENCES PARENT(ROWID)
);
所有这些都可以正常工作,并且我可以将数据绑定到我的模型并编辑字段等。我的问题是,如果我试图为这些模型创建记录,那么当CHILD的外键在PARENT中却无法同时创建时,该怎么办?
所以,我目前的基本步骤是:
PARENT
模型的列表PARENT
模型致电SaveChanges()
对于每个家长:
SaveChanges()
其他模型的数据库的其他操作和更新
SaveChanges()
我敢肯定我可以优化它,但这不是我所关心的。在我看来,应该有某种方法可以执行此操作,而无需手动查找FK或手动设置FK。如果需要,我可以这样做,但是我只想使用一个SaveChanges()
调用来在单个事务中推送这些命令。我正在寻找符合以下条件的东西:
获取要插入数据库的PARENT模型列表
其他模型的数据库的其他操作和更新
SaveChanges()
为了提供一些上下文,我的实际表中有许多列不能保证是唯一的(这就是为什么PK位于ROWID上的原因),并且这些行中的每一行都与子表具有非多对多的关系,其中子表也可能具有非唯一的行。并不是很理想,但是到目前为止,这是我们运营所需要的。我在此处包括伪代码,因为实际的代码是专有的,但是如果需要,我可能可以创建一个真实的模型。
有什么建议吗?
谢谢
编辑: 因此,我根据建议更改了代码以利用Navigation属性。这几乎可行。这是我的代码:
List<PARENT> parents = getParents();
List<CHILD> children = getChildren();
foreach (PARENT parent in parents)
{
db.PARENT.add(parent);
foreach (CHILD child in children)
{
child.PARENT = parent;
db.CHILD.add(child);
}
}
db.SaveChanges();
乍一看,这正是我想要的。但是,当我运行它时,子记录仅插入第一个父记录。因此,例如,如果我有3个PARENT记录和3个CHILD记录,那么我的CHILD表中应该有9个新记录。但是,在这段代码之后,第一个PARENT只有3条记录。
我假设这与以下事实有关:我反复使用相同的子级列表,而Entity Framework却以某种方式将其视为重复项。我将其按如下所示移动到PARENT for循环中,并且按预期工作:
List<PARENT> parents = getParents();
foreach (PARENT parent in parents)
{
db.PARENT.add(parent);
List<CHILD> children = getChildren();
foreach (CHILD child in children)
{
child.PARENT = parent;
db.CHILD.add(child);
}
}
db.SaveChanges();
但是,我不希望这样做,因为getChildren()函数相当麻烦。有什么想法吗?
答案 0 :(得分:1)
使用导航属性;将“ Child.Parent”导航属性设置为尚未保存的“ Parent”实体,EF会通过一次调用“ SaveChanges”的操作按正确的顺序插入它们。
答案 1 :(得分:0)
我使用下面的代码为一个国家表播种了初始dB值,该国家表中的城市,地区,邻里及其转换在一个dB内。
您可以实现类似的结构,以在同一dB调用中创建父代->子代->孙子实体;
var country = new MyCountry {
Title ="Syria",
ShortName="SYR",
Translations=new[]
{
new CountryTranslate { LCID=1, Name="سوريا" },
new CountryTranslate { LCID=31, Name="Suriye" },
new CountryTranslate {LCID=9, Name="Syria" }
},
Cities=new[]
{
new MyCity
{
Title="Lattakia",
ShortName = "LAT",
Translations=new[]
{
new CityTranslate { LCID=1, Name="اللاذقية" },
new CityTranslate {LCID=31, Name="Lazkiye" },
new CityTranslate {LCID=9, Name="Lattakia" }
},
Districts=new[]
{
new MyDistrict
{
Title="Owineh",
Translations=new[]
{
new DistrictTranslate { LCID=1, Name="العوينة" },
new DistrictTranslate { LCID=31, Name="Uveyne" },
new DistrictTranslate {LCID=9, Name="Owineh" }
},
Neighborhoods = new[]
{
new MyNeighborhood
{
Title="Reji",
Translations = new[]
{
new NeighborhoodTranslate { LCID=1, Name="الريجي"},
new NeighborhoodTranslate { LCID=31, Name="Eski Reji"},
new NeighborhoodTranslate { LCID=9, Name="Old Reji"}
}
}
}
}
}
}
}
}
context.SaveChanges();