在实体框架6中不需要声明关系时?

时间:2018-03-08 20:47:25

标签: c# entity-framework entity-framework-6 ef-fluent-api navigation-properties

在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; }
}    

Fluent 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:很多关系,我完全不需要在代码中有任何关系。我唯一需要的是1:1的关系。我错过了什么吗?大多数关系都是1:很多,所以它是否意味着Fluent API大部分时间用于1:1?

1 个答案:

答案 0 :(得分:2)

实体框架有一些您不需要明确定义的约定。

来自https://msdn.microsoft.com/en-us/library/jj679962(v=vs.113).aspx#Anchor_2

  

除了导航属性,我们建议您包含   表示依赖对象的类型上的外键属性。   与主要主键具有相同数据类型的任何属性   属性,名称遵循以下格式之一   表示关系的外键:&#39;&lt; navigation property   name&gt;&lt;主要主键属性名称&gt;&#39;,&#39;&lt; principal class   name&gt;&lt;主键属性名称&gt;&#39;或&#39;&lt;主要主键属性   名称&gt;&#39 ;.如果找到多个匹配,则在。中给出优先级   上面列出的订单。外键检测不区分大小写。什么时候   检测到外键属性,Code First推断出多重性   基于外键的可空性的关系。如果   该属性可以为空,然后将该关系注册为   可选的;否则,关系会按要求注册。