【发布时间】:2018-03-08 20:47:24
【问题描述】:
在 EF6 中,我们有两种方式来声明两个表之间的关系:
注解属性
Fluent API
今天(偶然)我删除了两个表之间的一个关系,一切都运行良好。我很惊讶,因为 EF 无法知道这两个表是如何连接的。
表格如下所示:
[Table("item")]
public class Item
{
public Item()
{
ItemNotes = new HashSet<ItemNote>();
}
[Key]
[Column("itemID", TypeName = "int")]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int itemID { get; set; }
public ICollection<ItemNote> ItemNotes { get; set; }
}
[Table("itemNotes")]
public class ItemNote
{
[Key]
[Column("id", TypeName = "int")]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Column("itemID", TypeName = "int")]
public int ItemId { get; set; }
[Column("note", TypeName = "varchar")]
[MaxLength(255)]
public string Note { get; set; }
}
流畅的 API:
public class MyContext : DbContext
{
public MyContext()
: base("name=MyContext")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer<MyContext>(null);
//I removed this relationship:
//modelBuilder.Entity<Item>().HasMany(i => i.ItemNotes).WithRequired().HasForeignKey(i => i.ItemId);
base.OnModelCreating(modelBuilder);
}
}
这是我做的测试:这是一个集成测试,连接到真实的数据库,获取带有注释的项目并测试 EF:
[TestCase]
public void QueryItemWithItemNotesTest()
{
FniContext fniContext = new FniContext();
int itemId = fniContext.Database.SqlQuery<int>("SELECT TOP(1) itemId FROM item WHERE itemId IN (SELECT itemId FROM dbo.itemNotes)").FirstOrDefault();
var item = fniContext.Items.AsNoTracking()
.Include(i => i.ItemNotes)
.Where(i => i.itemID == itemId).FirstOrDefault();
Assert.IsNotNull(item);
Assert.Greater(item.ItemNotes.Count, 0);
}
通过了!它加载所有笔记! 怎么会?!
我一直在调查,结果发现在 1:many 关系的情况下,我完全不必在代码中存在任何关系。我唯一需要的是 1:1 的关系。我错过了什么吗?大多数关系是 1:many,那么是不是说 Fluent API 大部分时间都是 1:1 使用的?
【问题讨论】:
-
即使在数据库级别上,您也不需要 FK 约束。您可以直接在数据库中使用原始 sql 测试它,并使用两个没有 FK 的表。换句话说,带有连接的 SELECT 可以在没有 FK 约束的情况下工作。但是,存在这些限制是有原因的,您应该始终使用它们:linkedin.com/pulse/importance-foreign-key-constraint-tim-miles 好吧,回到您的问题,EF 约定在您的案例中胜出。
标签: c# entity-framework entity-framework-6 ef-fluent-api navigation-properties