序列化类型 System.Data.Entity.DynamicProxies 的对象时检测到循环引用

1,序列化类型 System.Data.Entity.DynamicProxies 的对象时检测到循环引用

entity famework+asp.net mvc 做code first项目的时候,前台ajax请求到后台 JsonResult

在后台返回  return Json(list, JsonRequestBehavior.AllowGet)的时候,出错:

序列化类型 System.Data.Entity.DynamicProxies 的对象时检测到循环引用。

解决方法:

  1.可以在查询的时候这样子

复制代码
var list = from f in db.Categories
                       //这里要select new
                       select new
                       {
                           Id = f.Id,
                          Name = f.Name,
                          
                       };
复制代码

2.你可以尝试删除所有的导航属性的virtual关键字禁用延迟加载和创建代理,然后使用预先加载,而不是显式地加载所需的对象图:

复制代码
public ActionResult GetAll()
{
    return Json(Context.Categories
                           .Include(o => o.Products)
                           ,
        JsonRequestBehavior.AllowGet);
}
复制代码

看起来像是不依赖于延迟加载,无论如何,因为你使用virtual属性延迟加载对象图,可能会造成现在的系列化的麻烦。
3.没有必要删除virtual关键字导航性能(这将使延迟加载的模型完全不可能)。这足以创建代理(以及禁用延迟加载)禁用代理扰乱序列一样,具体情况:

Context.Configuration.ProxyCreationEnabled = false;

这将禁用,仅适用于特定的上下文实例Context创建代理。


2,

为什么 序列化类型为“System.Data.Entity.DynamicProxies.Photos....这个会的对象时检测到循环引用。

今天遇到下面这个问题,小子留了下来供大家参考

 

 

 

“/”应用程序中的服务器错误。


 

序列化类型为“System.Data.Entity.DynamicProxies.Photos_1F5D250F2735650E782711718DE2EFF2BBEA68EE8F6C5A1CF253FAABD0681F7B”的对象时检测到循环引用。

 

源码如下:

 public ActionResult GetAllUserInfos()
        {
            //方法内部给前台返回当前页的数据:  json:{total:30,rows:[]}
 
            //当前表格会自动发送异步请求到后台,然后传递参数是:rows  page
            var pageSize = Request["rows"] == null ? 10 : int.Parse(Request["rows"]);
            var pageIndex = Request["page"] == null ? 1 : int.Parse(Request["page"]);
 
          
            //当前页的对象      分页
            var pageData = db.Photos.OrderBy(u => u.PId)
                .Skip(pageSize * (pageIndex - 1))
                .Take(pageSize);
 
            //var pageData = db.Photos.ToList();
            //为啥有这个对象:前台需要这样的对象,先组装成一个匿名类然后序列化
            var result = new { total = db.Photos.Count(), rows = pageData };
 
            return Json(result, JsonRequestBehavior.AllowGet);
        }

在百度查看了下方案,说加一句这个

db.Configuration.ProxyCreationEnabled = false;  我试了一下果然好用,但是不明白,为什么会出现这种错误,求各位大神的指导

 

 

 

 

好像知道了.因为这个表和另一个表是有一对多关系的,当序列化表1的时候,会找到和另一个表2关联的字段,就会到另一个表2中序列化,然后另一个表2中也有一个字段和表1相关联.这样.序列化就会发生这种错误! 相关解决方案有3种:

1.最简单的方式就是从Entity Framework着手,停用LazyLoading与ProxyCreation.因为LazyLoading停用后那么当JSON.Net解析Order对象时其属性Order_Details会返回null(不会自动加载).所以也就避免了此问题

当然此方式的缺点会导致后续程序存取Entity Object时牺牲了LazyLoading的方便性,需要手动处理此问题.

 

1. db.Configuration.LazyLoadingEnabled = false;
2. db.Configuration.ProxyCreationEnabled = false;
3.  
4. return db.Orders.AsEnumerable();

 

2.设定JSON.Net忽略循环参考

透过APP_Start的WebApiConfig.cs,设定config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;

使用这个方式时要注意,它只是忽略循环参考的错误,但实际上还是会自动一层层解析要输出的对象之属性,所以若数据会相依有可能会产生无穷循环.

 

3.设定JSON.Net避免循环参考

透过APP_Start的WebApiConfig.cs,设定

config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Serialize;

config.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;

这种做法与2的差异在于它会将重复过的对象用一个代表取代,譬如底下JSON格式
1: [{"$id":"1","Category":{"$id":"2","Products":[{"$id":"3","Category":{"$ref":"2"},"Id":2,"Name":"Yogurt"},{"$ref":"1"}],"Id":1,"Name":"Diary"},"Id":1,"Name":"Whole Milk"},{"$ref":"3"}]

所以对于数据而言这种作法还是会自动一层层解析要输出的对象之属性,只是避免输出太大量数据.

 

4.手动设定避免循环参考

如同3的模式,透过[JsonIgnore] 与[JsonObject(IsReference = true)] 细部设定,可以更精确的设定每个要输出的属性.

缺点是1.设定繁杂. 2.只能通用设定无法例外. 3.因为必须直接或透过 partial class方式设定,故无法将设定与Entity Object class做分离

 

以上作法实际上都有其优缺点, 并没有一个可以通用的模式, 须看需求而定,这问题与同早期RIA Service的问题相同,但这边提供一种比较通用的模式就是采用方法1+方法2或3.

停用LazyLoading,而使用程序的方式(透过 Include方法)决定那些属性要输出.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要使用 System.Data.Entity DbContext 创建 SQLite 数据库和数据表,您需要安装两个 NuGet 包: 1. System.Data.SQLite.Core:提供 SQLite 数据库的核心功能。 2. System.Data.SQLite.EF6:提供 Entity Framework 6 的 SQLite 数据提供程序。 安装 NuGet 包后,您可以使用以下步骤创建 SQLite 数据库和数据表: 1. 在应用程序中创建一个派生自 DbContext 的类。例如: ```csharp using System.Data.Entity; public class MyDbContext : DbContext { public MyDbContext() : base("MyConnectionString") { } public DbSet<MyEntity> MyEntities { get; set; } } ``` 2. 在应用程序的配置文件(如 app.config 或 web.config)中添加连接字符串。例如: ```xml <connectionStrings> <add name="MyConnectionString" connectionString="Data Source=MyDatabase.sqlite" providerName="System.Data.SQLite.EF6" /> </connectionStrings> ``` 3. 在应用程序启动,将数据库初始化为最新模型。例如: ```csharp Database.SetInitializer(new CreateDatabaseIfNotExists<MyDbContext>()); ``` 4. 在 DbContext 中定义实体类。例如: ```csharp public class MyEntity { public int Id { get; set; } public string Name { get; set; } } ``` 5. 在 DbContext 中使用 DbSet 属性定义数据表。例如: ```csharp public DbSet<MyEntity> MyEntities { get; set; } ``` 6. 使用 DbContext.SaveChanges() 方法保存更改。例如: ```csharp using (var context = new MyDbContext()) { var entity = new MyEntity { Name = "Test" }; context.MyEntities.Add(entity); context.SaveChanges(); } ``` 这样就可以使用 System.Data.Entity DbContext 创建 SQLite 数据库和数据表了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值