2011-09-30 90 views
7

所以继承人交易我有EntityFramework to Json解决方法?

模型

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; } 
} 

....以下模型(在序列化类型的对象... DynamicProxies时检测到循环引用)(这些模型被连接到EfDbContext)连接到以下库...

接口/存储库

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(); 
} 

在我的HomeController()我有一个JsonResult metod,我想返回上下文。 这里是方法

JSON请求

[HttpGet] 
    public JsonResult GetNews() 
    { 
     var p = newsRepository.AllIncluding(news => news.Category, news => news.Image); 
     return Json(p, JsonRequestBehavior.AllowGet); 
    } 

我得到以下错误:

而串行化类型“System.Data.Entity.DynamicProxies的目的时检测到循环引用.News_96C0B16EC4AC46070505EEC7537EF3C68EE6CE5FC3C7D8EBB793B2CF9BD391B3' 。

我猜这事做与惰性加载的东西(IAM目前学习C#)我发现这篇文章这个...

http://hellowebapps.com/2010-09-26/producing-json-from-entity-framework-4-0-generated-classes/

,但我没有得到它的工作。 ..我能读懂的代码是,他们试图深入搜索槽对象......不仅如此,我无法弄清楚。

我的问题是我如何传递lazyLoading对象?成json /序列化程序 还是不存在,我可以如何继续的任何想法?

回答

12

由于Json是一个基于树的序列化格式,因此存在像A→B-> A这样的引用问题。
我读过某处,您可以在视图模型中使用属性来防止出现此错误。但还没有测试过。

你可以改变你的代码如下(使用匿名类型)成功地检索项:

var p = newsRepository.AllIncluding(news => news.Category, news => news.Image) 
    .Select(n => new {id = n.Id, Body = n.Body}); 

包括你希望在最后Select方法来显示任何其他财产。这使得你的Json结果更加轻量。

+0

谢谢回答!,是我像你一样解决它,但我想使用动态(lazyloading),得到json的结果,因为它的unnececary工作重新在控制器中的模型,这就是我认为...以及我会尝试如果ScriptIgnore的作品..谢谢! – Martea

+0

@Martea:没问题。如果您认为这是您问题的答案,请将其标记为答案。 – Kamyar

6

为了增加Kamyar的答案...

的AllIncluding方法只适用,如果你正在使用MVC的脚手架。请参阅以下链接以获取该方法的列表: Mvc 3 Scaffolding: the Model passed to the View throws SQL errror

我试过使用它,但仍遇到循环引用错误,因为根对象仍作为代理返回。所以我定制了方法来暂时关闭EF上下文中的ProxyCreationEnabled标志,并且急切地加载方法参数中列出的指定属性。请参阅以下链接了解更多详情: Loading from database without proxy classes?

为了这个工作,查询过,而背景是尚客来执行,所以我不得不打电话查询的ToList()方法来执行查询,然后返回IEnumerable,而不是IQueryable。这为我做了这份工作。

这里是我使用的方法(“_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; 
} 

这可以再开始使用以下语法叫:

IEnumerable<News> newsItems = newsRepository.ListIncluding<News>(news => news.Category, news => news.Image);