首先在实体框架代码中使用导航属性

2024-02-16

Context:

  • 代码优先,实体框架 4.3.1;
  • 用户----主题,1对多关系;
  • User with public virtual ICollection<Topic> CreatedTopics导航属性(延迟加载);
  • Topic with public 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
    }
    
  • Result: “w3wp.exe 中发生未处理的 microsoft .net 框架异常”

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

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

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

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

谢谢你的帮助!

Dean


这不是代码优先或 EF 的问题 - 这是序列化的问题。默认情况下,用于将对象图转换为 Web API 消息中传递的某种表示形式的序列化程序无法使用循环引用。根据您想要使用的消息格式,Web API 默认使用不同的序列化器 -here http://www.asp.net/web-api/overview/formats-and-model-binding/json-and-xml-serialization更多关于 Web API 使用的默认序列化器以及如何更改它的方法。以下文字假设您正在使用DataContractJsonSerializer or DataContractSerializer(应该是 XML 序列化的默认值),但对于 JSON.NET 也是可能的(应该是 JSON 序列化的默认值 - JSON 序列化可以切换为DataContractJsonSerializer但默认的序列化器更好)。

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

当您使用启用延迟加载的方式序列化实体图时,您可以序列化Topic和它的Creator但连载也会访问CreatedTopicsproperty => 所有相关主题均延迟加载并通过序列化处理并序列化继续访问Creator所有新加载的主题!这个过程一直持续到没有其他对象需要延迟加载为止。因此,在序列化实体时永远不应该使用延迟加载。

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

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

首先在实体框架代码中使用导航属性 的相关文章

随机推荐