2011-09-30 29 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);