When declaring relationship is not necessary in Entity Framework 6?

喜欢而已 提交于 2020-01-05 08:08:10

问题


In EF6 we have two ways to declare relationship between two tables:

  • Annotations Attributes

  • Fluent API

Today (by accident) I removed one relationship between two tables and everything kept working well. I was very surprised because there was no way EF would know how those two tables are connected.

Tables look like that:

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

Here is the test I made: It's an integration test, that connects to the real database, gets items with notes and tests the 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);
    } 

It passes! It loads all notes! How come?!

I kept investigating and it turned out that in case of 1:many relationship I totally don't have to have any relationship in the code. The only time I need it is with 1:1 relationship. Am I'm missing something? Most of relationships are 1:many, so does it mean Fluent API is used for 1:1 most of the time?


回答1:


Entity Framework has some conventions that you do not need to define explicitly.

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

In addition to navigation properties, we recommend that you include foreign key properties on the types that represent dependent objects. Any property with the same data type as the principal primary key property and with a name that follows one of the following formats represents a foreign key for the relationship: '<navigation property name><principal primary key property name>', '<principal class name><primary key property name>', or '<principal primary key property name>'. If multiple matches are found then precedence is given in the order listed above. Foreign key detection is not case sensitive. When a foreign key property is detected, Code First infers the multiplicity of the relationship based on the nullability of the foreign key. If the property is nullable then the relationship is registered as optional; otherwise the relationship is registered as required.



来源:https://stackoverflow.com/questions/49182158/when-declaring-relationship-is-not-necessary-in-entity-framework-6

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!