【问题标题】:Convert Entity Framework Object to JSON Object将实体框架对象转换为 JSON 对象
【发布时间】:2011-10-24 13:30:04
【问题描述】:

我正在尝试根据我的实体类型 SYSTEM_AUDIT_SHEET 发布一个 JSONJ 对象的通用处理程序:

SYSTEM_AUDIT_SHEET sheet = ctx.SYSTEM_AUDIT_SHEET
                              .Where(s => s.SYSTEM_KEY == system_key_dec)
                              .Select(s => s)
                              .OrderByDescending(s => s.AUDIT_SHEET_VERSION)
                              .First();

HttpContext.Current.Response.Write(serializer.Serialize(sheet));

但我收到以下错误:

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

为什么我不能将实体转换为 JSON?

【问题讨论】:

  • 创建一个类似于您要序列化但没有循环引用的对象的新类。从工作表对象填充该类中的数据并将其序列化。由于这类问题,直接序列化 Entity Framework Object 是一种不好的做法。
  • 重复问题;答案是“使用 JSON.Net”,它有几种解决方案,无需复制/粘贴类。 stackoverflow.com/questions/4606232/…

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


【解决方案1】:

您不能将对象转换为引用自身的 json,因为这会创建一个无限长的 json 字符串。

例如,下面的伪代码不起作用,因为它设置了一个循环引用(Dog >> Bone >> Dog...):

class Dog {
    private Bone myBone;
    public Dog() {
        myBone = new Bone(this);
    }
}

class Bone {
    private Dog buriedBy;
    public Bone(Dog d) {
        buriedBy = d;
    }
}

谷歌搜索“json 循环引用”似乎有一些很好的解决方案。查看前两个堆栈溢出链接。

【讨论】:

【解决方案2】:

问题可能是您的SYSTEM_AUDIT_SHEET 包含一个引用SYSTEM_AUDIT_SHEET 类型实例的属性,或者它包含一个指向具有SYSTEM_AUDIT_SHEET 实例指针的对象的属性。序列化这样一圈指针会导致一个永远不会结束的序列化过程。

在进行序列化之前,您需要将您的 SYSTEM_AUDIT_SHEET 转换为不(直接或间接)引用自身的类型。您可以创建一个全新的类型并编写代码以从您的SYSTEM_AUDIT_SHEET 实例化这种类型(AutoMapper 可能在这里派上用场)。但是,我倾向于发现在大多数情况下,只使用匿名类型会更容易:

SYSTEM_AUDIT_SHEET sheet = /*some sheet*/
var json = new {
  sheet.Id,
  sheet.RevisionNumber,
  sheet.Title
};
return serializer.Serialize(json);

编辑

如果您想使用 AutoMapper 并假设您的工作表看起来像

class SYSTEM_AUDIT_SHEET 
{
    public int Id { get; set; }
    public SYSTEM_AUDIT_SHEET SomeOtherAuditSheet { get;set;}
    public string Title { get;set;}
}

你可以创建一个像

这样的类型
class JSON_SYSTEM_AUDIT_SHEET
{
    public int Id { get; set; }
    public int SomeOtherAuditSheetsId { get;set;}
    public string Title { get;set;}
}

当您的应用程序启动时(例如,在 Application_Start 中)您配置 AutoMapper:

AutoMapper.Mapper.CreateMap<SYSTEM_AUDIT_SHEET, JSON_SYSTEM_AUDIT_SHEET>()
  .ForMember(dest => dest.SomeOtherAuditSheetsId, opt => opt.MapFrom(src => src.SomeOtherAuditSheet.Id));

IdTitle 属性将直接从SYSTEM_AUDIT_SHEET 映射到JSON_SYSTEM_AUDIT_SHEET,因为它们在两种类型中具有相同的名称。属性SomeOtherAuditSheetsId 需要特殊配置,因为源类型上没有具有该确切名称的属性。

当您想将 SYSTEM_AUDIT_SHEET 转换为 JSON_SYSTEM_AUDIT_SHEET 时:

return AutoMapper.Mapper.Map<SYSTEM_AUDIT_SHEET , JSON_SYSTEM_AUDIT_SHEET >(sheet);

您可能想看看AutoMapper's flattening features

希望这会有所帮助。

【讨论】:

  • 是的,但由于有 30 个属性,我不想手动执行此操作。我想这就是自动映射器的用途?你能告诉我它是如何使用的吗?
  • +1 用于 AutoMapper。任何人都知道自动为此复制 POCO 的现有工具或模板?
猜你喜欢
  • 2012-10-25
  • 1970-01-01
  • 1970-01-01
  • 2012-08-14
  • 2011-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多