【问题标题】:Using navigation properties in entity framework code first首先在实体框架代码中使用导航属性
【发布时间】:2012-07-03 16:33:48
【问题描述】:

上下文:

  • 代码优先,实体框架 4.3.1;
  • 用户----主题,一对多关系;
  • Userpublic virtual ICollection<Topic> CreatedTopics 导航属性(延迟加载);
  • Topicpublic virtual User Creator 导航属性;
  • DataServiceController : DbDataController<DefaultDbContext>,Web API 测试版,ASP.NET MVC 4 测试版,单页应用程序;
  • System.Json 用于 Json 序列化;
  • Web API 操作:

    public IQueryable<Topic> GetTopics()
    {
        // return DbContext.Topics;                   // OK
        return DbContext.Topics.Include("Creator");   //With Exception
    }
    
  • 结果:“w3wp.exe 中出现未处理的 microsoft .net 框架异常”

这里的问题似乎是:我不应该在两个实体中添加导航属性(导致循环引用?),如果我删除 User 类中的 CreatedTopics 导航属性,它会再次好的。

所以,在上面列出的类似上下文中,这是我的问题:

  1. 一对多关系的情况下如何处理Navigation Properties;
  2. 更进一步,多对多关系怎么样,我必须把它分成两个1对多关系吗?
  3. 使用导航属性的最佳做法和注意事项是什么?

我已经阅读了很多相关的帖子,但仍然不够清楚:(,

感谢您的帮助!

院长

【问题讨论】:

    标签: entity-framework-4 ef-code-first asp.net-web-api navigation-properties


    【解决方案1】:

    这不是代码优先或 EF 的问题,而是序列化的问题。默认情况下,用于将对象图转换为 Web API 消息中传递的某种表示的序列化程序无法使用循环引用。根据您要使用的消息格式,Web API 默认使用不同的序列化程序 - here 更多的是关于 Web API 使用的默认序列化程序以及如何更改它的方式。以下文本假设您正在使用DataContractJsonSerializerDataContractSerializer(应该是 XML 序列化的默认值)但 JSON.NET 也是可能的(应该是 JSON 序列化的默认值 - JSON 序列化可以切换到 DataContractJsonSerializer 但是默认序列化器更好)。

    那么你能做什么?您可以告诉序列化程序它应该通过使用DataContract(IsReference = true) 标记您的类并使用DataMember 属性标记每个传递的属性来跟踪这些循环引用(查看链接文章以了解如何使用JSON.NET 实现它)。这将允许序列化器正确识别周期,序列化理论上会成功。理论上因为这也要求不使用延迟加载。否则,您可以序列化比预期更多的数据(在某些灾难性场景中,它可能导致序列化数据库的全部内容)。

    当您启用延迟加载来序列化实体图时,您会序列化Topic 及其Creator,但序列化也会访问CreatedTopics 属性=> 所有相关主题都被延迟加载并通过序列化处理,并且序列化继续访问@ 987654330@ 所有新加载的主题!这个过程一直持续到没有其他对象可以延迟加载。因此,您在序列化实体时绝不应该使用延迟加载。

    其他选项是从序列化中排除反向引用。你只需要序列化Creator。您不需要序列化CreatedTopics,因此您可以使用IgnoreDataMember 属性(对于JSON.NET 为JsonIgnore)标记属性。问题是,如果您还具有用于返回 User 及其所有 CreateTopics 的 Web API 操作,则由于该属性,这将不起作用。

    最后一个选项是不使用实体。此选项通常用于 Web 服务,您可以在其中创建满足特定操作要求的特殊 DTO 对象,并在操作内部处理实体和 DTO 之间的转换(可能借助 AutoMapper 等工具)。

    处理一对一、一对多或多对多关系没有区别。如果两侧都有导航属性,则必须始终处理此问题。

    【讨论】:

    • DataContractJsonSeriaizer 是 Web API Beta 的默认 Json 序列化程序吗?
    • 我暂时用DataContract(IsReference = true)DataMember,有没有详细的文章讲这个?我也对 DTO 选项感兴趣,但目前未能通过,将花更多时间在上面,感谢您的好答案。
    猜你喜欢
    • 2015-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-03
    相关资源
    最近更新 更多