【问题标题】:Understanding many to many relationships and Entity Framework了解多对多关系和实体框架
【发布时间】:2011-02-26 20:20:21
【问题描述】:

我正在尝试了解实体框架,并且我有一个表“用户”和一个表“页面”。这些与联结表“UserPages”以多对多关系相关。首先,我想知道我是否使用多对多正确设计了这种关系:一个用户可以访问多个页面,并且每个页面都可以被多个用户访问......,所以我使用正确many2many?

其次,更重要的是,据我了解 m2m 关系,User 和 Page 表不应重复信息。 IE。每个用户和每个页面应该只有一个记录。但是在实体框架中,我如何能够为同一用户添加对同一页面的新访问?也就是说,我想我可以简单地使用 LINQ 查询返回的 IEnumerable 上的 Count() 方法来获取用户访问某个页面的次数。

但我认为没有办法做到这一点。在 Linq to Sql 中,我可以访问联结表并在那里添加记录,以反映某个用户对某个页面的添加访问,根据需要多次。但是在 EF 中我无法访问联结表。我只能从 User 转到 Pages 集合,反之亦然。

我确定我误解了关系或其他什么,但我就是不知道如何对此建模。我总是可以在 Page 表中有一个 Count 列,但据我了解,您不应该设计这样的数据库表,这些值应该由查询收集......

请帮助我理解我做错了什么......

【问题讨论】:

    标签: entity-framework linq-to-entities many-to-many


    【解决方案1】:

    你做得对

    在实体数据模型 (EDM) 中,多对多关系可以表示有或没有连接表,这取决于它是否包含一些额外的字段。有关详细信息,请参阅下面的文章。


    在您的情况下,User 实体将直接引用 Page 实体的集合,反之亦然,因为您的模型不包含 的映射User_Page 加入表。

    为了增加对用户特定页面的访问,您可以执行以下操作:

    using (var context = new YourEntityModelObjectContext())
    {
         var page = context.Pages.FirstOrDefault(p => p.Url == "http://someurl");
         var user = context.Users.FirstOrDefault(u => u.Username == "someuser");
    
         user.Pages.Add(page);
    
         context.SaveChanges();
    }
    

    或者你可以从关系的另一端来做:

    using (var context = new YourEntityModelObjectContext())
    {
         var page = context.Pages.FirstOrDefault(p => p.Url == "http://someurl");
         var user = context.Users.FirstOrDefault(u => u.Username == "someuser");
    
         page.Users.Add(user);
    
         context.SaveChanges();
    }
    

    在这两种情况下,都会将一条新记录添加到 User_Page 连接表中。

    如果您需要检索特定用户访问的页面数,您可以简单地执行以下操作:

    using (var context = new YourEntityModelObjectContext())
    {
         var user = context.Users.FirstOrDefault(u => u.Username == "someuser");
         var visitCount = user.Pages.Count;
    }
    

    相关资源:

    【讨论】:

    • 谢谢,但除非我以某种方式误解了你,否则这是行不通的,我已经尝试过了。我收到此异常:“无法更新 EntitySet 'UserPages',因为它有一个 DefiningQuery,并且 元素中不存在 元素来支持当前操作。”我不太确定这意味着什么,因为我对 EF 还很陌生...
    • 听起来“UserPages”实体映射到“User”和“Page”表之间的连接表。您不需要在模型中包含该实体,而是在“用户”和“页面”实体之间创建直接的多对多关系。查看这篇文章以了解有关如何执行此操作的更多详细信息:learnentityframework.com/LearnEntityFramework/tutorials/…
    • 不,模型中没有连接表,只有 User 和 Page 类。所以 UserPages 表似乎只是在后台以某种方式使用。当我在对话框中创建实体数据模型时,我确实选择了所有表,但我猜如果我不这样做,关系就不会包含在模型中?但是同样,即使我选择了所有表,连接表也没有包含在生成的模型中......
    • 我明白了。连接表不是概念模型 (CSDL) 的一部分,但包含在存储模型 (SSDL) 中。两者都是 EDM 模型的一部分。您之前描述的异常是由于连接表没有在数据库中定义的主键引起的。在这种情况下,Visual Studio 将在存储模型(“DefiningQuery”)中生成一个“视图”,默认情况下无法更新。我的建议是您在数据库中为连接表定义一个主键,然后更新您的模型(在 EDM 设计器中,右键单击并选择“从数据库更新模型”)
    • 对于浏览这篇文章的其他人:考虑使用复合主键。我刚刚遇到了一个没有主键的连接表的问题,花了 30 分钟才向 uber-dev 寻求帮助并得到了这个建议。 . .效果很好!只是在连接表中添加一个普通的主键就给我带来了其他错误,而且真的是一个杂物。
    猜你喜欢
    • 1970-01-01
    • 2017-01-28
    • 2011-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多