无法将实体框架归零或从零到一的关系工作

时间:2017-01-19 12:14:19

标签: c# mysql entity-framework

我是Entity Framework的新手,我花了最后一个 4小时天试图让(看似简单的)简单的工作关系。

我有三个班:人,房子,车库

  • 一个人可以没有或多个(0..n)房屋和车库
  • 一个房子可以有(0..1)一个车库,并且只能属于一个人
  • 因此,车库也可以拥有(0..1)一个房子,并且只能属于一个人
  • 车库没有房屋和没有车库的房屋
  • 在任何时候都没有相关人员的车库或房子(这很容易,我想我有那个)

到目前为止,我已经阅读了10篇不同的文档,这些文档对我来说只会让人感到困惑。我尝试使用注释解决它,但似乎我也必须使用这种流畅的api东西。

我得到的最远的是将房屋和车库与一个人相关联,但不是彼此相关。现在我不得不定义一个关系的原则结束,我甚至不理解它应该做什么。

现在我得到了

  

无法确定相关操作的有效排序。由于外键约束,模型要求或存储生成的值,可能存在依赖关系。

试图解决一系列不同的错误。

通过编写我自己的查询,我一直在PHP中手动实现这些关系。这是我第一次在一个更大的框架中进行数据库工作,这应该会让事情变得更容易,但到目前为止,我已经在从DatabaseReader填充对象方面取得了更大的成功。

从我的逻辑角度来看,三个类/表之间的关系应该非常简单,但我找不到类似关系的例子,或者让它只是工作。

所以我的问题是:

  • 零或一对零或一对关系真的那么特别,首先在代码中很难设计吗?
  • Garage表是否不需要House表的外键,因为可以通过过滤GarageId的House表来找到相应的House?我已经尝试在代码中实现House的查找,但注意到它打破了很多LINQ,因为它不再是数据库属性了。
  • 我尝试过Annotations和Fluent API,所有来自SO的0..1到0..1(或实际上,任何其他)关系的顶级示例,尝试在模型构建器中交换字段,因为它看起来不正确在数据库中...直到达到DB看起来还不错的程度,但代码仍然拒绝工作。我还能尝试什么?
  • 也许我一直在做所有的DB错误,并且这样的关系对所有参与者都是不健康的。在这种情况下,你会建议我尝试复制上述人 - 房 - 车库关系有哪些替代方案?我可以在众议院和车库之间推出任何辅助课程来使其发挥作用吗?

我准备了一个演示项目:https://github.com/Zaphox/DatabaseTest
它包含三个类,上下文和应该成功完成(但没有)的关系测试。

感谢您提供解决此问题的所有帮助和提示!

Ž。

更新1

在尝试了所有建议之后,我注意到任何循环关系都会导致EF中的错误,而且似乎无法创建这样的引用,甚至0..1到0..1自引用似乎不起作用。< / p> 然而,我已经实施了一个至少让我工作的黑客,但它太可怕了,我希望有人告诉我有更好的方法。

  1. 只有房屋有车库参考,反之亦然
  2. 要获得属于Garage的House,需要单独的查询(db.Buildings.OfType<House>().Where(h => h.Garage.Id == myGarage.Id).First()
  3. 我还考虑在Garage中添加一个NotMapped House字段,它自己查找房子,但它会干扰其他查询,所以这也不是一个有效的选项。

    最让我烦恼的是,有很多关于自我引用和喜欢的文章,但仅限于1到n关系。任何尝试使1到1或0..1到0..1的关系总是失败,EF无法弄清楚“顺序”。

    事情是EF认为必须在House表中放置GarageId FK,在Garage表中放置HouseId FK,这是无稽之谈。我只需要在House表中使用GarageId,它可以用作向后引用。我可以实现此代码,但它与EF查询不兼容,并且通常会干扰其他正在运行的查询,因为您无法一次运行两个查询。

    GitHub上的演示项目使用当前版本进行更新,有点可行,但每次我想找到属于车库的房子时都需要进行大量额外的查询。

2 个答案:

答案 0 :(得分:2)

显然问题是HouseGarage之间的关系。

  

我只需要在House表中使用GarageId,它可以用作向后引用。

实际上,当您在Garage类上放置 House导航属性时,默认情况会发生这种情况(唯一的区别是FK列名称为{{1 }})。这称为单向关联。通过这样的设置,EF认为Garage_Id是从属的,House是主体,两者都是可选的。重要的是FK列是在依赖表中创建的。

所以这就是您目前在测试项目中所具有的功能。通过将Garage属性添加到House类来使关联双向化时会出现问题:

Garage

在这种情况下,EF没有足够的信息您的意图是什么,因此您需要提供该信息。请记住,您需要public class House { public int Id { get; set; } public Garage Garage { get; set; } public string Style { get; set; } } public class Garage { public int Id { get; set; } public House House { get; set; } public int Size { get; set; } } 表中的GarageId FK,所以这里是您需要添加的相应Fluent配置(House部分是可选的 - 如果您跳过它,FK列将会像你当前的项目一样被称为Map

Garage_Id

一切都会按预期工作。

答案 1 :(得分:1)

实体框架不喜欢没有明确主体的关系。在这种情况下,任何一个实体都可以不存在另一个实体,也不依赖于另一个实体。

我建议您重新设计模型,以便有一个BuildingHouse来自的Garage抽象类。然后,您可以将PersonBuilding相关联,并在具体类型“住宅”和Garage中找到关联的Building链接。

示例:

public abstract class Building
{
    public Person Person { Get; Set; }

    public Building Building { Get; Set; }
}

public class House : Building
{
    // Other House properties
}

public class Garage : Building
{
    // Other Garage properties
}

然后,在业务逻辑中,您可以强制关联的建筑物与this.GetType() != Building.GetType()

之类的类型不能相同