0

我们将 MVC 与实体框架结合使用。在某些时候,我们正试图在两个实体之间建立联系。这在单元测试中工作正常,但在从 MVC 控制器方法尝试时会出现以下错误:

“保存不为其关系公开外键属性的实体时发生错误。EntityEntries 属性将返回 null,因为无法将单个实体标识为异常源。通过在实体类型中公开外键属性,可以更轻松地在保存时处理异常。“</p>

(精简)类:

public class Position : Entity
{
   public string Function { get; set; }
   public Organization Organization{ get; set; }
   // public Guid? OrganizationId { get; set; }
   // works when enabled!
 }

public class Organization: Entity
{
   public string Name { get; set; } 
   public IList<Position> Contacts
   {
      get {return contacts;} 
      set { contacts = value; }
   }

   public class EntityConfiguration :
        EntityConfigurationBase<Organization>
   {
       public EntityConfiguration()
       {
          HasMany(p => p.Contacts)
              .WithOptional(y => y.Organization)
       }
   }

   private IList<Position> contacts = new List<Position>();
}

失败的(精简)控制器方法:

    [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
            );
    }
}

为什么 MVC 需要 OrganizationId 外键属性?是否有一个不需要模型中所有外键的简单修复?

4

0 回答 0