Dea*_*ean 6 navigation-properties entity-framework-4 ef-code-first asp.net-web-api
语境:
User
使用public virtual ICollection<Topic> CreatedTopics
导航属性(延迟加载);Topic
具有public virtual User Creator
导航属性;DataServiceController : DbDataController<DefaultDbContext>
,Web API beta,ASP.NET MVC 4 Beta,单页应用程序;Web API操作:
public IQueryable<Topic> GetTopics()
{
// return DbContext.Topics; // OK
return DbContext.Topics.Include("Creator"); //With Exception
}
Run Code Online (Sandbox Code Playgroud)结果:"w3wp.exe中出现未处理的microsoft .net框架异常"
这里的问题似乎是:我不应该在两个实体中添加导航属性(导致循环引用?),如果我CreatedTopics
在User
类中删除导航属性,它将再次正常.
所以,在上面列出的类似上下文中,这是我的问题:
我看过很多相关的帖子,但还不够清楚:(,
谢谢你的帮助!
院长
这不是代码优先或EF的问题 - 这是序列化的问题.用于将对象图转换为Web API消息中传递的某些表示形式的序列化程序默认情况下无法使用循环引用.根据您要使用的消息格式,Web API默认使用不同的序列化程序 - 这里有更多关于Web API使用的默认序列化程序以及如何更改它的方法.下面的文本假设您正在使用DataContractJsonSerializer
或DataContractSerializer
(应该是XML序列化的默认设置),但JSON.NET也是如此(对于JSON序列化应该是默认的 - 可以切换到JSON序列化,DataContractJsonSerializer
但默认的序列化程序更好).
那么你能做什么?您可以告诉序列化程序它应该DataContract(IsReference = true)
通过使用DataMember
属性标记您的类和每个传递属性来跟踪这些循环引用(请查看链接文章以了解如何使用JSON.NET实现它).这将允许序列化器正确识别循环,并且序列化在理论上将成功.理论上因为这也要求不使用延迟加载.否则,您可以序列化比预期更多的数据(在某些灾难性情况下,它可能导致序列化数据库的整个内容).
当您启用延迟加载序列化实体图时,您会serailze a Topic
和它Creator
但序列化也将访问CreatedTopics
property =>所有相关主题都是延迟加载并通过序列化处理并且序列化继续访问Creator
所有新加载的主题!此过程将继续,直到没有其他对象延迟加载.因此,在序列化实体时不应使用延迟加载.
其他选项是从序列化中排除反向引用.你只需要序列化Creator
.您不需要序列化,CreatedTopics
因此可以使用IgnoreDataMember
属性标记属性(JsonIgnore
对于JSON.NET).问题是,如果你还有Web API动作用于返回User
所有CreateTopics
这些因为属性而无法工作.
最后一个选项不使用实体.此选项通常用于Web服务,您可以在其中创建满足特定操作要求的特殊DTO对象,并处理操作中实体和DTO之间的转换(可以借助AutoMapper等工具).
处理一对一,一对多或多对多关系之间没有区别.如果双方都有导航属性,则必须始终处理此问题.
归档时间: |
|
查看次数: |
2890 次 |
最近记录: |