2011-09-30 16 views
7

để heres thỏa thuận tôi cóEntityFramework đến Json workaround? (A tham chiếu vòng tròn đã được phát hiện trong khi xuất một đối tượng kiểu ... DynamicProxies)

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

.... mô hình sau đây (các mô hình này được kết nối đến EfDbContext) kết nối với kho lưu trữ sau đây ...

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

Trong HomeController() của tôi, tôi nhận được một JodResult metod mà tôi muốn trả về ngữ cảnh. Dưới đây là phương pháp

Json Yêu cầu

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

tôi nhận được lỗi sau:

Một tham chiếu vòng tròn đã được phát hiện trong khi xuất một đối tượng kiểu 'System.Data.Entity.DynamicProxies .News_96C0B16EC4AC46070505EEC7537EF3C68EE6CE5FC3C7D8EBB793B2CF9BD391B3 '.

Tôi đoán rằng đây có cái gì để làm với những thứ lazyloading (Iam đang học về C#) tôi tìm thấy bài viết này về vấn đề này ...

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

nhưng i didnt có được nó để làm việc. .. những gì tôi có thể đọc về mã là họ đã cố gắng để tìm kiếm chiều sâu máng đối tượng ... nhiều hơn mà tôi không thể tìm ra.

câu hỏi của tôi là làm cách nào để tôi có thể chuyển vào đối tượng lazyLoading? vào json/serializer hoặc không tồn tại, bất kỳ suy nghĩ nào về cách tôi có thể tiếp tục?

Trả lời

12

Vì Json là định dạng tuần tự dựa trên cây, nó có vấn đề với các tham chiếu như A-> B-> A.
Tôi đã đọc ở đâu đó mà bạn có thể sử dụng thuộc tính trong chế độ xem của mình để ngăn chặn lỗi này. Nhưng chưa thử nghiệm nó.

Bạn có thể thay đổi mã của bạn vào (các kiểu nặc danh sử dụng) sau đây để lấy các mặt hàng thành công:

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

Bao gồm bất kỳ tài sản khác mà bạn muốn hiển thị trong phương pháp cuối cùng Select. Điều này làm cho kết quả Json của bạn cũng nhẹ hơn.

+0

Cám ơn trả lời Tôi đã muốn sử dụng năng động (lazyloading), để có được kết quả json vì công việc không cần thiết của nó để tạo lại mô hình trong bộ điều khiển, đó là những gì tôi nghĩ ... tôi sẽ thử nếu ScriptIgnore hoạt động .. cảm ơn! – Martea

+0

@Martea: Không sao cả. Nếu bạn nghĩ rằng đây là câu trả lời cho câu hỏi của bạn, hãy đánh dấu câu trả lời đó là câu trả lời. – Kamyar

6

Để thêm vào câu trả lời của Kamyar ...

Phương pháp AllIncluding chỉ có sẵn nếu bạn đang sử dụng MVC giàn giáo. xem liên kết sau đây để biết danh sách phương thức: Mvc 3 Scaffolding: the Model passed to the View throws SQL errror

Tôi đã thử sử dụng, nhưng vẫn gặp lỗi tham chiếu vòng tròn vì đối tượng gốc vẫn được trả về dưới dạng proxy. Vì vậy, tôi đã tùy chỉnh phương thức để tạm thời tắt cờ ProxyCreationEnabled trên ngữ cảnh EF và háo hức nạp các thuộc tính được chỉ định được liệt kê trong tham số của phương thức.Xem liên kết sau để biết thêm chi tiết: Loading from database without proxy classes?

Để làm việc này, truy vấn phải được thực hiện trong khi cài đặt vẫn tắt, vì vậy tôi phải gọi phương thức ToList() của truy vấn để thực hiện truy vấn, và sau đó trả về IEnumerable, thay vì IQueryable. Điều này đã làm công việc cho tôi.

Dưới đây là phương pháp tôi đã sử dụng ("_context" là tên biến cho bối cảnh EF của tôi):

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

này sau đó có thể được gọi bằng cách sử dụng cú pháp sau:

IEnumerable<News> newsItems = newsRepository.ListIncluding<News>(news => news.Category, news => news.Image); 
Các vấn đề liên quan