问题描述
上下文:
- code首先,实体框架4.3.1;
- 用户----主题, 1对多关系;
-
用户
与public虚拟的ICollection<&主题GT; CreatedTopics
导航属性(延迟加载); -
主题
与公共虚拟用户的创造者
导航属性; -
DataServiceController:DbDataController< DefaultDbContext>
,网络API测试版,ASP.NET MVC 4 Beta版,单页应用; - System.Json的JSON序列;
-
网页API操作:
- Code First, Entity Framework 4.3.1;
- User ---- Topic, 1 to Many relation;
User
withpublic virtual ICollection<Topic> CreatedTopics
Navigation Property(Lazy Loading);Topic
withpublic virtual User Creator
Navigation Property;DataServiceController : DbDataController<DefaultDbContext>
, Web API beta, ASP.NET MVC 4 Beta , Single Page Application;- System.Json for Json serialization;
Web API Action:
public IQueryable<Topic> GetTopics()
{
// return DbContext.Topics; // OK
return DbContext.Topics.Include("Creator"); //With Exception
}
结果:未处理的Microsoft .NET Framework异常出现在w3wp.exe的
这里的问题似乎是:我不应该的添加导航属性两个实体(?原因循环引用),如果我删除 CreatedTopics
导航属性在用户
类,这将是确定一次。
The Problem here seems to be: I should not Add Navigation Property in both Entities(Cause Circular Reference?), and if I delete the CreatedTopics
Navigation Property in User
Class, It will be OK again.
因此,在类似语境像上市的上方,这里是我的问题:
So, In a similar Context like listed above, Here are my questions:
- 如何处理与导航属性在 1对多关系的情况;
- 进一步,怎么样的多对多的关系,我一定把它分成两个 1对多的关系;
- 什么是使用导航属性的最佳做法和precautions?
- How to deal with Navigation Properties in the situation of 1 to Many relation;
- Further more, how about a Many to Many relation, do i have to divide it into two 1 to Many relations;
- What is the Best Practices and Precautions of using Navigation Properties?
我看了很多相关的帖子,但仍不够明确:(
I Have read many related posts, but still not clear enough :(,
感谢您的帮助!
院长
推荐答案
这是不是code第一或EF的一个问题 - 这是序列化的问题。只需用你的对象图转换为在Web API的消息通过一些重新presentation串行不能与默认循环引用工作。根据您要使用的Web API消息格式默认情况下使用不同的序列化 - here更多的是被Web API以及如何去改变它方式使用默认的序列化。下面的文字假设您正在使用 DataContractJsonSerializer
或的DataContractSerializer
(应该是默认XML序列化),但同样是可能的为JSON.NET。(应该是默认JSON序列 - JSON序列化可以切换到 DataContractJsonSerializer
但是默认的序列化越好)
This is not a problem of code first or EF - it is a problem of serialization. Simply the serializer used to convert your object graph to some representation passed in a Web API message is not able to work with circular references by default. Depending on the message format you want to use Web API uses different serializers by default - here is more about default serializers used by Web API and about the way how to change it. The following text suppose that you are using DataContractJsonSerializer
or DataContractSerializer
(should be default for XML serialization) but the same is possible for JSON.NET (should be default for JSON serialization - JSON serialization can be switched to DataContractJsonSerializer
but the default serializer is better).
所以,你可以做什么?你可以告诉它应该与 DataContract(IsReference = TRUE)
和每个通过的财产与数据成员标记你的类跟踪这些循环引用串行code>属性(检查是否有说明如何与JSON.NET实现它链接的文章)。这将允许串行正确认识循环和序列化将在理论上获得成功。从理论上讲,因为这也要求不使用延迟加载。否则,你可以序列化(在某些情况下灾难性它可能会导致你的序列数据库全部内容)比你预期的要更多的数据。
So what you can do? You can tell the serializer that it should track those circular references by marking your classes with DataContract(IsReference = true)
and each passed property with DataMember
attribute (check the linked article for description how to achieve it with JSON.NET). This will allow serializer correctly recognizing cycles and the serialization will in theory succeed. In theory because this also demands to not using lazy loading. Otherwise you can serialize much more data than you expected (in some catastrophic scenarios it can lead to serializing whole content of your database).
当你序列与延迟加载实体图形使你serailze一个主题
和创
,但系列化还将访问 CreatedTopics
属性=>所有相关主题是懒惰的加载和序列化和系列化加工继续参观创
所有新加载主题!此过程继续进行,直到没有其他目的是懒负载。因此序列化的实体,当你不应该使用延迟加载。
When you serialize entity graph with lazy loading enabled you serailze a Topic
and its Creator
but serialization will also visit CreatedTopics
property => all related topics are lazy loaded and processed by serialization and serialization continues to visit Creator
of all newly loaded topics! This process continues until there is no other object to lazy load. Because of this you should never use lazy loading when serializing entities.
另一个选择是排除从后面系列化参考。你只需要序列化创
。你并不需要序列化 CreatedTopics
这样你就可以用标记 IgnoreDataMember
属性(属性JsonIgnore
为JSON.NET)。问题是,如果你也有返回的Web API行动用户
与所有他的 CreateTopics
这不会因为工作属性。
Other option is to exclude back reference from serialization. You just need to serialize Creator
. You don't need to serialize CreatedTopics
so you can mark the property with IgnoreDataMember
attribute (JsonIgnore
for JSON.NET). The problem is that if you also have Web API action for returning User
with all his CreateTopics
this will not work because of the attribute.
最后一个选项是不使用的实体。此选项通常在您创建的特殊对象DTO具体操作满足要求,你处理的实体和DTO的之间的转换操作内(可能像AutoMapper一些工具帮助)Web服务使用。
The last option is not using entities. This option is usually used in web services where you create special DTO objects satisfying requirements for specific operation and you handle conversion between entities and DTOs inside the operation (possible with help of some tool like AutoMapper).
有是处理一到一,一到多,或许多一对多关系之间没有差别。如果你有两面导航属性必须始终处理这个问题。
There is no difference between handling one-to-one, one-to-many, or many-to-many relations. If you have navigation properties on both sides you must always deal with this problem.
这篇关于在实体框架code。使用导航性能第一的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!