实体框架代码优先协会/ FK问题和假设/默认值

问题描述:

我的方式实体框架能够拿起实体之间的关系非常困惑。我有这几个问题。

I am very confused by the way Entity Framework is able to pick up on relationships between entities. I have a few questions on this.

在一个简单的测试应用程序,我有一桌子的人,以及票据表格和图片资产表。

In a simple test application, I have a table of people, and a table of notes, and a table of picture assets.


  1. 有很多的照片,每次由一个人所拥有的(一个人可以拥有不止一个)。

  2. 有许多短信,每次由一个人所拥有的(一个人可以拥有不止一个)。

  3. 最后一个人有一个标志是一个图片。

    public class Person
    {
        public int ID { get; set; }

        public string name { get; set; }

        public Picture logo { get; set; }
    }

    public class Note
    {

        public int ID { get; set; }

        public string Text { get; set; }

        public Person Owner { get; set; }
    }


 public class Picture
    {

        public int ID { get; set; }

        public string Path { get; set; }

        public Person Owner { get; set; }
    }

当我尝试运行,我得到的错误无法确定类型......之间的关联的主要终点。

When I try to run, I get the error "Unable to determine the principal end of an association between the types ....".

(如果我把Person.logo场,编译/运行,然后手动将其添加到SQL与FK关系以来,它的工作原理100%的预期......我似乎无法制定出如何从EF本身)设置此。

(If I drop the Person.logo field, compile/run, then manually add it in to SQL, along with the FK relationship, it works 100% as expected... I just can't seem to work out how to set this from EF itself).

灿你的错误帮助吗?我在这里看了不少答案,但我似乎无法适应它来解决我的错误。

Can you help with the error? I have read quite a few answers here, but, I just can't seem to adapt it to fix my error.

不过,现在我有一个一对多和多对一(我不认为这是归类为多对多?),我只是不知道如何创建对象的人,其中一个FK非可空和FK尚不存在。

However, now I have a one to many and a many to one (I don't think this is classed as many to many?), I just don't understand how to create people objects, where a FK is non nullable and the FK doesn't exist yet.

一个解决方案,我发现,我真的不喜欢就是让person.picture栏为空,然后创建一个人,然后创建一个图片,然后将图片设置人员对象......但是,理想,我不希望它为空。 。凡事总有一个画面

A solution I found, which I really don't like is to make the person.picture column nullable, then create a person, followed by creating a picture, then assign a picture to the person object... but, ideally I don't want it nullable. There should always be a picture.

向下滚动你澄清一个答案。

下面两种方式来实现这一目标,一个方法是删除 导航交叉引用应用的 1:N

Here are two ways to achieve this, one way is to remove the cross reference navigation by applying 1:N.

    public class Person
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public virtual Picture Logo { get; set; }
    }

    public class Note
    {
        public int ID { get; set; }
        public string Text { get; set; }
    }


    public class Picture
    {
        public int ID { get; set; }
        public string Path { get; set; }
    }

这是一个非常便宜的解决方案,你可能不希望更多音符或图片不是人...

This is a really cheap solution, you probably don't want more notes or pictures than persons...

所以,使用的数据注释的指示外键,这将保持导航什么,的 1:1

So, use Data Annotations to instruct what the foreign key is, this will keep navigation and 1:1.

    public class Person
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public virtual Picture Logo { get; set; }
    }

    public class Note
    {
        [Key, ForeignKey("Person")]
        public int OwnerID { get; set; }
        public string Text { get; set; }
        public virtual Person Owner { get; set; }
    }


    public class Picture
    {
        [Key, ForeignKey("Person")]
        public virtual int OwnerId { get; set; }
        public string Path { get; set; }
        public virtual Person Owner { get; set; }
    }



正如你所看到的,因为1:1的关系的画面和说明将使用相同的ID。如果你的键没有命名的ID,你需要添加一个 KeyAttribute ,在这种情况下,我们还要添加的 ForeignKeyAttribute

As you can see, because of the 1:1 relationship the picture and note will use the same ID. If your key is not named ID, you need to add a KeyAttribute, in this case we also add the ForeignKeyAttribute.

请注意,您应该使用虚拟等等事情加载只有当你要求他们,你很可能不希望数据库查询资料图片,如果你只想要的人的名字。

Please note that you should use virtual so that things load only when you request them, you most likely don't want the database to query the Picture information if you only want the name of the Person.

关联属性的虚拟将默认延迟加载。这意味着,如果你检索产品的实体,它的分类信息不会从数据库中,直到你访问它的类别属性(或者,除非你明确地表明,当你写你的LINQ查询检索类别数据应被检索的检索产品对象)。

Association properties that are marked as virtual will by default be lazy-loaded. What this means is that if you retrieve a Product entity, its Category information will not be retrieved from the database until you access its Category property (or unless you explicitly indicate that the Category data should be retrieved when you write your LINQ query to retrieve the Product object).

— 斯科特顾 - 使用EF代码先用现有的数据库

BULDING进一步的外键通过返回到一个1:N结构的 的ICollection< T> ;一旦你得到你的人喜欢 VAR老板= Person.find的(BossID)然后你可以访问 boss.Pictures 这将有各种各样的图片。您也可以将 boss.Logo 是那些图片之一。


New answer regarding your clarification:

Bulding further on the Foreign Keys by going back to a 1:N structure with ICollection<T>; once you obtain your person like var boss = Person.Find(BossID) you can then access boss.Pictures which will have the various pictures. You can also assign boss.Logo to be one of those pictures.

    public class Person
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public virtual Picture Logo { get; set; }
        public ICollection<Picture> Pictures { get; set; }
        public ICollection<Note> Notes { get; set; }
    }

    public class Note
    {
        public int ID { get; set; }
        [ForeignKey("Person")]
        public int OwnerID { get; set; }
        public string Text { get; set; }
        public virtual Person Owner { get; set; }
    }


    public class Picture
    {
        public int ID { get; set; }
        [ForeignKey("Person")]
        public virtual int OwnerId { get; set; }
        public string Path { get; set; }
        public virtual Person Owner { get; set; }
    }