实体框架将POCO序列化为JSON

实体框架将POCO序列化为JSON,json,entity-framework,serialization,entity-framework-4.1,Json,Entity Framework,Serialization,Entity Framework 4.1,我正在使用EF4.1,我有一个POCO对象,我想序列化为JSON,我读到在使用延迟加载时这样做有问题,但我不确定我是否可以,因为消息可以包含消息的集合 有没有办法做到这一点?将此类对象序列化为JSON 我的消息对象看起来像: public class Message { [Key] public int Id { get; set; } public int? ParentId { get; set; } public string Title { get; se

我正在使用EF4.1,我有一个POCO对象,我想序列化为JSON,我读到在使用延迟加载时这样做有问题,但我不确定我是否可以,因为
消息
可以包含
消息
的集合

有没有办法做到这一点?将此类对象序列化为JSON

我的
消息
对象看起来像:

public class Message
{
    [Key]
    public int Id { get; set; }
    public int? ParentId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public DateTime CreatedAt { get; set; }
    public DateTime? LastModified { get; set; }

    public virtual User User { get; set; }

    public virtual Message Parent { get; set; }

    public virtual ICollection<Message> Children { get; set; }
}
公共类消息
{
[关键]
公共int Id{get;set;}
public int?ParentId{get;set;}
公共字符串标题{get;set;}
公共字符串内容{get;set;}
public DateTime CreatedAt{get;set;}
公共日期时间?LastModified{get;set;}
公共虚拟用户用户{get;set;}
公共虚拟消息父级{get;set;}
公共虚拟ICollection子项{get;set;}
}
这个怎么样:

  • 将您的类标记为
    [Serializable]
  • 使用JsonSerializer将对象序列化为JSON
  • 也许在EF查询中的属性上使用渴望加载

使用Include()加载它。示例linq:

var serializeMe = (from m in MyContext.Message.Include("User") where m.Id == someValue select m).ToList();

这将告诉EF立即加载用户导航属性,而不是延迟加载,那么序列化程序应该不会有问题。

问题是循环引用。避免这种情况的一种简单方法是使用Json.Net而不是默认的MVC Json序列化程序。最新版本的Json.Net将使用开箱即用的循环引用序列化对象。关于这个问题的更多信息,让我们分部分来讨论

为什么会发生这种情况?

因为你有虚拟财产。如果您使用的是EF,那么如果您使用的是延迟加载,那么您实际上需要它们。您可以通过以下示例将EF配置为不执行此操作:

        context.Configuration.ProxyCreationEnabled = false;
其中context是您的ObjectContext或DbContext。。。假设您使用的是EF。但对于大多数情况,这并不是一个好办法

可能的解决方案

正如我常说的:“没有好的或坏的解决方案,只有不同的方法,这取决于上下文”,也就是说,您可以创建动态对象

如果您只需要序列化一个唯一的对象,您可以这样做

        Json(new {@property1=yourObject.property1, @property2=yourObject.property2})
如果您有一个列表,那么您可以这样做:

        var list = new List<dynamic>();

        foreach(var item in myRepository.GetAll())
        {
            list.Add(new
            {
                @property1= item.property1,
                @property2= item.property2,
                @property3= item.property3
            });
        }
        return Json(list, JsonRequestBehavior.DenyGet);
var list=newlist();
foreach(myRepository.GetAll()中的var项)
{
列表。添加(新)
{
@property1=项目。property1,
@property2=项目。property2,
@property3=项目。property3
});
}
返回Json(列表,JsonRequestBehavior.DenyGet);
我试着让它尽可能的通用。我希望这能帮助别人


致以最诚挚的问候,祝你度过愉快的一天!:)

谢谢你的详细回答,但我恐怕虚拟财产不是这样加载的…@CD:我缺少什么?对于集合和单个属性,
virtual
属性已序列化,非常好:谢谢
ReferenceLoopHandling.Ignore
和一个自定义的
ContractResolver
完成了这个技巧:-)包括相关的实体解决了我序列化EF对象图时遇到的一个问题,因为我能够从类中有问题的属性中去掉虚拟关键字。谢谢
        var list = new List<dynamic>();

        foreach(var item in myRepository.GetAll())
        {
            list.Add(new
            {
                @property1= item.property1,
                @property2= item.property2,
                @property3= item.property3
            });
        }
        return Json(list, JsonRequestBehavior.DenyGet);