C# 从MVC保存类之间的关联时出现实体框架错误
我们将MVC与实体框架结合使用。 在某种程度上,我们正试图在两个实体之间建立联系。这在单元测试中可以正常工作,但从MVC控制器方法尝试时会出现以下错误: “保存不公开外部数据的实体时出错 关系的键属性。EntityEntries属性 将返回null,因为无法将单个实体标识为 异常的来源。可以在保存时处理异常 通过在实体类型中公开外键属性使其更容易。” (精简)类别: 通过的单元测试:C# 从MVC保存类之间的关联时出现实体框架错误,c#,asp.net-mvc,entity-framework,C#,Asp.net Mvc,Entity Framework,我们将MVC与实体框架结合使用。 在某种程度上,我们正试图在两个实体之间建立联系。这在单元测试中可以正常工作,但从MVC控制器方法尝试时会出现以下错误: “保存不公开外部数据的实体时出错 关系的键属性。EntityEntries属性 将返回null,因为无法将单个实体标识为 异常的来源。可以在保存时处理异常 通过在实体类型中公开外键属性使其更容易。” (精简)类别: 通过的单元测试: [TestMethod] public void LinkOrganizationToPositionT
[TestMethod]
public void LinkOrganizationToPositionTest()
{
// arrange
DbModel dbModel;
Organization org;
Position pos;
Guid orgId;
using (dbModel = new DbModel())
{
dbModel.Database.Delete();
dbModel.Database.Create();
// - first organization
org = dbModel.Organizations.Create();
org.Name = "TestOrgFirst";
dbModel.Entry(org).State = EntityState.Added;
pos = dbModel.Positions.Create();
pos.Function = "TestFunc";
dbModel.Entry(pos).State = EntityState.Added;
// - link pos to first org
pos.Organization = org;
org = dbModel.Organizations.Create();
org.Name = "TestOrgSecond";
dbModel.Entry(org).State = EntityState.Added;
orgId = org.Id;
dbModel.SaveChanges();
}
// act
// - obtain "fresh" model
using (dbModel = new DbModel())
{
// - get second org
org = dbModel.Organizations.Find(orgId);
pos = dbModel.Positions.Find(pos.Id);
pos.Organization = org;
dbModel.SaveChanges();
}
// assert
using (dbModel = new DbModel())
{
Position actual =
dbModel.Positions
.Include("Organization")
.First(x => x.Id.Equals(pos.Id));
// - link was saved
Assert.AreEqual(
"TestOrgSecond",
actual.Organization.Name
);
}
}
为什么MVC需要OrganizationId外键属性?
是否有一个简单的修复程序不需要模型中的所有外键?我可以衷心建议显式实现外键。它让生活变得更简单!只是好奇。你是否尝试过将职位添加到组织的联系人中?@ilmatte:是的,我甚至尝试过在Organi中向集合添加职位组织的组织化和设置Position@Dabblernl:我可以这样看,但这比丑陋更糟糕:OO实现不应该需要关系外键。@kc了解外键关联与独立关联(没有原始FK属性)的优势。无论从哪个角度看,EF类模型仍然是DAL,因此请针对其主要职责对其进行优化。您已经有了主键、基类
实体、嵌套映射类。原始FKs不会让它变得更“糟糕”:
[HttpPost]
public ActionResult Edit(Position position, string organizationId = "")
{
if (!ModelState.IsValid)
{
return View(position);
}
db.Entry(position).State = EntityState.Modified;
if (!string.IsNullOrEmpty(organizationId))
{
Guid orgId = Guid.Parse(organizationId);
Organization organization =
db.Organizations
.First(x => x.Id.Equals(orgId));
position.Organization = organization;
}
db.SaveChanges();
RedirectToAction("Index");
}
[TestMethod]
public void LinkOrganizationToPositionTest()
{
// arrange
DbModel dbModel;
Organization org;
Position pos;
Guid orgId;
using (dbModel = new DbModel())
{
dbModel.Database.Delete();
dbModel.Database.Create();
// - first organization
org = dbModel.Organizations.Create();
org.Name = "TestOrgFirst";
dbModel.Entry(org).State = EntityState.Added;
pos = dbModel.Positions.Create();
pos.Function = "TestFunc";
dbModel.Entry(pos).State = EntityState.Added;
// - link pos to first org
pos.Organization = org;
org = dbModel.Organizations.Create();
org.Name = "TestOrgSecond";
dbModel.Entry(org).State = EntityState.Added;
orgId = org.Id;
dbModel.SaveChanges();
}
// act
// - obtain "fresh" model
using (dbModel = new DbModel())
{
// - get second org
org = dbModel.Organizations.Find(orgId);
pos = dbModel.Positions.Find(pos.Id);
pos.Organization = org;
dbModel.SaveChanges();
}
// assert
using (dbModel = new DbModel())
{
Position actual =
dbModel.Positions
.Include("Organization")
.First(x => x.Id.Equals(pos.Id));
// - link was saved
Assert.AreEqual(
"TestOrgSecond",
actual.Organization.Name
);
}
}