EntityFramework 到 Json 的解决方法?(在序列化类型为...DynamicProxies 的对象时检测到循环引用)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7608372/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
EntityFramework to Json workaround? ( A circular reference was detected while serializing an object of type...DynamicProxies)
提问by Martea
so heres the deal i have
所以这是我的交易
Models
楷模
public class News
{
public News()
{
this.Created = DateTime.Now;
}
public int Id { get; set; }
public string Title { get; set; }
public string Preamble { get; set; }
public string Body { get; set; }
public DateTime Created { get; set; }
public int UserId { get; set; }
public virtual User User { get; set; }
public int CategoryId { get; set; }
public int ImageId { get; set; }
public virtual Image Image { get; set; }
public virtual Category Category { get; set; }
}
public class Image
{
public int Id { get; set; }
public string Name { get; set; }
public string ImageUrl { get; set; }
public Byte[] ImageData { get; set; }
public string ImageMimeType { get; set; }
}
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
}
....following models(these models are connected to the EfDbContext) connected to following repository...
....以下模型(这些模型连接到 EfDbContext)连接到以下存储库...
Interface/Repository
接口/存储库
public class NewsRepository : INewsRepository
{
EfDbContext context = new EfDbContext();
public IQueryable<News> All
{
get { return context.News; }
}
public IQueryable<News> AllIncluding(params Expression<Func<News, object>>[] includeProperties)
{
IQueryable<News> query = context.News;
foreach (var includeProperty in includeProperties) {
query = query.Include(includeProperty);
}
return query;
}
public News Find(int id)
{
return context.News.Find(id);
}
public void InsertOrUpdate(News news)
{
if (news.Id == default(int)) {
// New entity
context.News.Add(news);
} else {
// Existing entity
context.Entry(news).State = EntityState.Modified;
}
}
public void Delete(int id)
{
var news = context.News.Find(id);
context.News.Remove(news);
}
public void Save()
{
context.SaveChanges();
}
}
public interface INewsRepository
{
IQueryable<News> All { get; }
IQueryable<News> AllIncluding(params Expression<Func<News, object>>[] includeProperties);
News Find(int id);
void InsertOrUpdate(News news);
void Delete(int id);
void Save();
}
In my HomeController() i got a a JsonResult metod that i want to return the context. Here is the Method
在我的 HomeController() 中,我得到了一个 JsonResult 方法,我想返回上下文。这是方法
Json Request
JSON 请求
[HttpGet]
public JsonResult GetNews()
{
var p = newsRepository.AllIncluding(news => news.Category, news => news.Image);
return Json(p, JsonRequestBehavior.AllowGet);
}
I get the following error:
我收到以下错误:
A circular reference was detected while serializing an object of type 'System.Data.Entity.DynamicProxies.News_96C0B16EC4AC46070505EEC7537EF3C68EE6CE5FC3C7D8EBB793B2CF9BD391B3'.
在序列化类型为“System.Data.Entity.DynamicProxies.News_96C0B16EC4AC46070505EEC7537EF3C68EE6CE5FC3C7D8EBB793B2CF9BD391B3”的对象时检测到循环引用。
I guessed that this has something to do with the lazyloading stuff(Iam currently learning about C#) i found this article about this...
我猜这与延迟加载的东西有关(我目前正在学习 C#)我发现了这篇关于这个的文章......
http://hellowebapps.com/2010-09-26/producing-json-from-entity-framework-4-0-generated-classes/
http://hellowebapps.com/2010-09-26/production-json-from-entity-framework-4-0-generated-classes/
but i didnt get it to work... what i could read about the code was that they were tryin to depth search trough the object... more than that i couldn't figure out.
但我没有让它工作......我能读到的关于代码的内容是他们试图通过对象进行深度搜索......除此之外我无法弄清楚。
my question is how to i can pass in lazyLoading objects? into json/serializer or does it not exist, any thoughts of how i can proceed?
我的问题是如何传入lazyLoading 对象?进入 json/serializer 或者它不存在,我有什么想法可以继续吗?
回答by Kamyar
Since Json is a tree-based serialization format, it has problems with references like A->B->A.
I've read somewhere that you can use ScriptIgnoreattribute in your viewmodels to prevent this error. But have not tested it.
由于 Json 是一种基于树的序列化格式,因此在使用 A->B->A 等引用时存在问题。
我在某处读到过,您可以在视图模型中使用ScriptIgnore属性来防止此错误。但是没有测试过。
You can change your code to the following (use anonymous types) to retrieve the items successfully:
您可以将代码更改为以下内容(使用匿名类型)以成功检索项目:
var p = newsRepository.AllIncluding(news => news.Category, news => news.Image)
.Select(n => new {id = n.Id, Body = n.Body});
Include any other property you wish to display in the last Selectmethod. This makes your Json results more lightweight too.
包括您希望在最后一个Select方法中显示的任何其他属性。这也使您的 Json 结果更轻量级。
回答by Andy Thomas
To add to Kamyar's answer...
要添加到 Kamyar 的答案...
The AllIncluding method is only available if you are using MVC scaffolding. see the following link for a listing of the method: Mvc 3 Scaffolding: the Model passed to the View throws SQL errror
AllInclusion 方法仅在您使用 MVC 脚手架时可用。有关该方法的列表,请参见以下链接: Mvc 3 Scaffolding:传递给视图的模型引发 SQL 错误
I tried using it, but still encountered the circular reference error, since the root objects were still being returned as proxies. So I customised the method to temporarily turn off the ProxyCreationEnabled flag on the EF context, and eagerly load the specified properties listed in the method's parameter. See the following link for further details: Loading from database without proxy classes?
我尝试使用它,但仍然遇到循环引用错误,因为根对象仍然作为代理返回。因此,我自定义了该方法以暂时关闭 EF 上下文中的 ProxyCreationEnabled 标志,并急切地加载该方法参数中列出的指定属性。有关更多详细信息,请参阅以下链接: 从没有代理类的数据库加载?
In order for this to work, the query had to be performed while the setting was still off, so I had to call the query's ToList() method to perform the query, and then returned the IEnumerable, rather than IQueryable. This did the job for me.
为了使其工作,必须在设置仍然关闭时执行查询,因此我必须调用查询的 ToList() 方法来执行查询,然后返回 IEnumerable,而不是 IQueryable。这为我完成了工作。
Here is the method I used ("_context" is the variable name for my EF context):
这是我使用的方法(“_context”是我的 EF 上下文的变量名):
public IEnumerable<TEntity> ListIncluding<TEntity>(params Expression<Func<TEntity, object>>[] includeProperties)
where TEntity : class
{
bool cachedSetting = _context.Configuration.ProxyCreationEnabled;
_context.Configuration.ProxyCreationEnabled = false;
IQueryable<TEntity> query = _context.Set<TEntity>();
foreach (var includeProperty in includeProperties)
{
query = query.Include(includeProperty);
}
IEnumerable<TEntity> list = query.ToList();
_context.Configuration.ProxyCreationEnabled = cachedSetting;
return list;
}
This can then get called using the following syntax:
然后可以使用以下语法调用它:
IEnumerable<News> newsItems = newsRepository.ListIncluding<News>(news => news.Category, news => news.Image);

