Entity Framework Code First关联/外键问题和假设/默认值

3
我对Entity Framework如何识别实体之间的关系感到非常困惑。以下是我的一些问题:
在一个简单的测试应用程序中,我有一个人员表、一个笔记表和一个图片资产表。
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; }
    }

当我尝试运行时,出现错误“无法确定类型之间关联的主要端点...”。
(如果我删除Person.logo字段,编译/运行,然后手动将其添加到SQL中,并建立FK关系,它会按预期100%工作... 我只是无法弄清如何从EF本身设置此项)。
你能帮忙解决这个错误吗?我在这里读了很多答案,但是我似乎无法调整它来修复我的错误。
然而,现在我有一个一对多和多对一(我不认为这被归类为多对多?),我只是不明白如何创建人员对象,在那里FK是非空的,而FK还不存在。
我找到的一个解决方案,我真的不喜欢,就是使person.picture列可为空,然后创建一个人,接着创建一个图片,然后将图片分配给人员对象... 但是,理想情况下,我不想让它可为空。应该始终有一张图片。
3个回答

2

旧答案,假设您的关系是一对一:

向下滚动以获取有关您澄清的答案。

有两种方法可以实现这一点,一种方法是通过应用 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; }
    }

这是一个非常便宜的解决方案,你可能不需要比人数更多的注释或图片...
因此,使用 数据注释 来指示外键是什么,这将保持导航和 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
请注意,您应该使用virtual,以便仅在请求时加载内容,如果您只想要人员的名称,则最好不要让数据库查询图片信息。
标记为virtual的关联属性默认情况下将进行延迟加载。这意味着如果您检索一个Product实体,其Category信息直到访问其Category属性时才会从数据库中检索(或者除非您在编写检索Product对象的LINQ查询时明确指示需要检索Category数据)。——Scott Gu - 使用现有数据库的EF Code First
关于您的澄清,新的答案如下:
进一步建立外键,回到一个1:N结构,使用ICollection<T>;一旦您获得了像var boss = Person.Find(BossID)这样的人物,您就可以访问boss.Pictures,其中包含各种图片。您还可以将boss.Logo指定为其中的一张图片。
    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; }
    }

我必须说,我并不完全理解 - 我正在写一个关于这个的后续问题...但是,只要它能工作,我就很高兴。话虽如此,我无法让它工作...我刚试着编译,但一直收到以下错误:http://i.imgur.com/v9vB8.png - Wil
@WilliamHilsum:显然,ICollection 似乎是自己进行惰性加载的。 - Tamara Wijsman
抱歉,我应该跟进一下,我已经清理并编译了,看起来似乎可以工作...现在我将尝试完全实现它。 - Wil

1

+1 约定很有趣,谢谢... 至于 DataAnnotations - 我知道那是我所需要的(或者流畅API),但我就是搞不清楚实际语法/注解所需 :( - Wil
很高兴您觉得这很有用。关于尝试解决这种特定情况,一方面我建议尽可能注释模型(特别是[Key]和[RelatedTo]),另一方面我可能会采取Database-First或Model-Fist方法,然后检查自动生成的类以获取线索。 - Nano Taboada

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

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


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

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

上述代码是正确的,在尝试了多次错误代码后,我得到了正确的代码。

希望对你有用。


修饰符“virtual”对此项无效。 - Michael Draper

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接