数据优先 - JSON循环引用序列化错误

时间:2014-08-05 07:13:33

标签: c# asp.net-mvc json entity-framework kendo-grid

首先,我在其他帖子中尝试了一些解决方案,但我仍然得到例外。

我有一个名为Driver的SQL表,它与名为DriversToCars的表有关系 她生成的Class就是这样:

CarsToDriver.cs

public partial class CarsToDriver
    {
        public CarsToDriver()
        {
            this.Role_TimeRestriction = new HashSet<Role_TimeRestriction>();
        }

        public System.Guid Id { get; set; }
        public System.Guid CarId { get; set; }
        public System.Guid DriverId { get; set; }
        public string KilometersDriven { get; set; }

        public virtual Car Car { get; set; }
        public virtual Driver Driver { get; set; }
        public virtual Role_DayRestriction Role_DayRestriction { get; set; }
        public virtual ICollection<Role_TimeRestriction> Role_TimeRestriction { get; set; }
    }

Driver.cs

   public partial class 
   {
     public Driver()
        {
            this.CarsToDrivers = new HashSet<CarsToDriver>();
        }

        public System.Guid Id { get; set; }
        public string Name { get; set; }
        public string FamilyName { get; set; }
        public string Licence { get; set; }
        public Nullable<short> ExperienceYears { get; set; }
        public int UserId { get; set; }

        public virtual ICollection<CarsToDriver> CarsToDrivers { get; set; }
    }
  }

DriverController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Script.Serialization;
using Dal;
using Kendo.Mvc.Extensions;
using Kendo.Mvc.UI;

namespace CarManagerWebApplication.Controllers
{
    public class DriversController : Controller
    {
        private CarManagerDbEntities db = new CarManagerDbEntities();
        private List<Driver> drivers = new List<Driver>();


        // GET: Drivers
        public ActionResult Index()
        {
            return View(db.Drivers);
        }


        public ActionResult Read([DataSourceRequest] DataSourceRequest request)
        {

            var data = db.Drivers;
            //Project into anonymous objects because Serializers
            //can't handle circular refs in the EF magic
            var collection = data.Select(o => new
            {
                Name = o.Name,
                FamilyName = o.FamilyName,
                Licence = o.Licence,
                Id = o.Id,
                UserId = o.UserId,
                ExperienceYears = o.ExperienceYears
            });
            return Json(collection,
                JsonRequestBehavior.AllowGet);
        }


        public ActionResult Update(Driver driver)
        {          
            if (driver != null && ModelState.IsValid)
            {
                var driversDb = db.Drivers;
                var target = driversDb.First(p => p.Id == driver.Id);
                target.Id = driver.Id;
                target.Name = driver.Name;
                target.FamilyName = driver.FamilyName;
                target.Licence = driver.Licence;
                target.ExperienceYears = driver.ExperienceYears;
                target.UserId = driver.UserId;
            }
            return Json(ModelState.ToDataSourceResult());
        }
    }
}

Index.cshtml

@using Telerik.Web.Mvc.UI
@using GridEditMode = Kendo.Mvc.UI.GridEditMode
@model IEnumerable<Dal.Driver>

@(Html.Kendo().Grid(Model)
      .Name("OrdersGrid")
      .Columns(columns =>
      {
          columns.Bound(o => o.Name);
          columns.Bound(o => o.FamilyName);
          columns.Bound(o => o.ExperienceYears);
          columns.Command(comm =>
          {
              comm.Edit();
          });
      })
      .Pageable()
      .Sortable()
      .Filterable()
      .Groupable()
          .DataSource(dataSource => dataSource
            .Ajax()
            .Model(model =>
                {
                    model.Id(p => p.Id);
                    model.Field(p => p.Id).Editable(false);
                })
            .Read(read => read.Action("Read", "Drivers"))
                .Update(update => update.Action("Update", "Drivers"))
        )
      )

我得到了这个例外:

System.InvalidOperationException was unhandled by user code

的HResult = -

2146233079

消息=

A circular reference was detected while serializing an object of type 'System.Data.Entity.DynamicProxies.CarsToDriver_8AC3275A855579C1DF78C72160EC6FFFC18C734305D85AF888DDAE0574680224'.

源=

System.Web.Extensions

堆栈跟踪:

 at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat, MemberInfo currentMember)
   at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat, MemberInfo currentMember)
   at System.Web.Script.Serialization.JavaScriptSerializer.SerializeEnumerable(IEnumerable enumerable, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat)
   at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat, MemberInfo currentMember)
   at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat, MemberInfo currentMember)
   at System.Web.Script.Serialization.JavaScriptSerializer.SerializeCustomObject(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat)
   at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat, MemberInfo currentMember)
   at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat, MemberInfo currentMember)
   at System.Web.Script.Serialization.JavaScriptSerializer.SerializeCustomObject(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat)
   at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat, MemberInfo currentMember)
   at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat, MemberInfo currentMember)
   at System.Web.Script.Serialization.JavaScriptSerializer.SerializeEnumerable(IEnumerable enumerable, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat)
   at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat, MemberInfo currentMember)
   at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat, MemberInfo currentMember)
   at System.Web.Script.Serialization.JavaScriptSerializer.SerializeCustomObject(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat)
   at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat, MemberInfo currentMember)
   at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat, MemberInfo currentMember)
   at System.Web.Script.Serialization.JavaScriptSerializer.SerializeEnumerable(IEnumerable enumerable, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat)
   at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat, MemberInfo currentMember)
   at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat, MemberInfo currentMember)
   at System.Web.Script.Serialization.JavaScriptSerializer.Serialize(Object obj, StringBuilder output, SerializationFormat serializationFormat)
   at System.Web.Script.Serialization.JavaScriptSerializer.Serialize(Object obj, SerializationFormat serializationFormat)
   at System.Web.Script.Serialization.JavaScriptSerializer.Serialize(Object obj)
   at Kendo.Mvc.Infrastructure.DefaultJavaScriptSerializer.Kendo.Mvc.Infrastructure.IJavaScriptSerializer.Serialize(Object )
   at Kendo.Mvc.Infrastructure.JavaScriptInitializer.Serialize(IDictionary`2 object)
   at Kendo.Mvc.Infrastructure.JavaScriptInitializer.Serialize(IDictionary`2 object)
   at Kendo.Mvc.Infrastructure.JavaScriptInitializer.Serialize(IDictionary`2 object)
   at Kendo.Mvc.Infrastructure.JavaScriptInitializer.InitializeFor(String selector, String name, IDictionary`2 options)
   at Kendo.Mvc.Infrastructure.JavaScriptInitializer.Initialize(String id, String name, IDictionary`2 options)
   at Kendo.Mvc.UI.Grid`1.WriteInitializationScript(TextWriter writer)
   at Kendo.Mvc.UI.WidgetBase.WriteHtml(HtmlTextWriter writer)
   at Kendo.Mvc.UI.Grid`1.WriteHtml(HtmlTextWriter writer)
   at Kendo.Mvc.UI.WidgetBase.ToHtmlString()
   at Kendo.Mvc.UI.Fluent.WidgetBuilderBase`2.ToHtmlString()
   at System.Web.HttpUtility.HtmlEncode(Object value)
   at System.Web.WebPages.WebPageExecutingBase.WriteTo(TextWriter writer, Object content)
   at System.Web.WebPages.WebPageBase.Write(Object value)
   at ASP._Page_Views_Drivers_Index_cshtml.Execute() in c:\Projetcs\CarManagerWebApplication\Views\Drivers\Index.cshtml:line 5
   at System.Web.WebPages.WebPageBase.ExecutePageHierarchy()
   at System.Web.Mvc.WebViewPage.ExecutePageHierarchy()
   at System.Web.WebPages.StartPage.RunPage()
   at System.Web.WebPages.StartPage.ExecutePageHierarchy()
   at System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage)
   at System.Web.Mvc.RazorView.RenderView(ViewContext viewContext, TextWriter writer, Object instance)
   at System.Web.Mvc.BuildManagerCompiledView.Render(ViewContext viewContext, TextWriter writer)
   at System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult)

1 个答案:

答案 0 :(得分:0)

如果您同时显示CarsToDriver代码会更好。 我想你有下一个案例:

  1. 您拥有CarsToDrivers集合的Driver对象不为空
  2. CarsToDrivers的每个项目都有Driver对象(后引用)
  3. 在序列化期间,您有循环引用 (Driver-&gt; CarsToDrivers [0] - &gt; Driver-&gt; CarsToDrivers [0] ...)
  4. 我建议创建特殊类DriverViewModel和CarsToDriversViewModel,它们将由您的视图使用。 CarsToDriversViewModel必须不能引用DriverViewModel,而DriverViewModel必须具有集合CarsToDriversViewModel