【问题标题】:How to serialize entity if using lazy loading in entity framework?如果在实体框架中使用延迟加载,如何序列化实体?
【发布时间】:2018-02-22 15:10:44
【问题描述】:

我刚开始学习实体框架,我面临与生成模型序列化相关的问题。我有一对多关系的表格,它们是国家和国家,因为一个国家有许多国家。我使用的是 DB first 方法,当我使用实体框架创建实体时,Country 类具有 ICollection 的一个属性。我阅读并发现这是导航属性。让我先显示生成的类,如下所示:

//这是生成的类。

 public class Country
    {
        public Country()
        {
                States = new HashSet<States>();
        }
        public int Id { get; set; }
        public string ContryCode  { get; set; } 
        public string ContryName  { get; set; }    
        public virtual ICollection<States> States{ get; set; }

    }

我生成了模型,然后我向前迈进了一步。然后,当我通过 ajax 请求获取 Country 列表时,我遇到了序列化问题。我用谷歌搜索了一些术语,例如延迟加载、急切加载和 n+1 问题。我详细阅读了它。我找到了一个关闭延迟加载的解决方案。现在的问题是我如何通过延迟加载来序列化我的模型?

我创建了 MetaData 类并使用了一些属性,如 ignoreXml 等,但没有任何帮助。顺便说一句,我使用的是 Asp.Net MVC 5,我想用延迟加载序列化我的模型。谁能解释一下?

【问题讨论】:

  • 我可以理解在一些批处理或胖客户端应用程序中为什么需要延迟加载。但是对于一个更适合延迟加载的 Web 应用程序,您有什么用例(除了不想考虑 .Include 之外)?
  • @KyleBurns 我没有任何用例。但我想知道我们是否在任何情况下都使用延迟加载。那么我们如何序列化模型呢?
  • 您是否收到“上下文处理”错误?
  • 那么我遇到了问题 什么问题?很可能是循环引用,因为States 还包含对Country 的引用,在这种情况下,延迟加载与它无关
  • 我的问题是“我们可以用延迟加载序列化”我们的模型吗?

标签: c# asp.net-mvc entity-framework serialization


【解决方案1】:

当您使用延迟加载时,会延迟执行,直到实际需要该属性的值。您可能会遇到错误,因为在访问属性时上下文已被释放。考虑以下场景:

  • 您有一个名为 Country 的对象,其中包含一个名为 States 的延迟加载属性。
  • 您从上下文中获取此对象。
  • 上下文已处理。
  • 您调用States 属性。
  • 该属性会寻找它来自的上下文。
  • 由于“上下文已被释放”而引发错误。

代码示例:

using(var context = new SomeEntityContext())
{
     var country = context.Countries.First();
}

//This will throw an error because the context was disposed of.
var states = country.States; 

序列化程序也会抛出错误,因为它会遍历对象的属性,找到States 并尝试获取其值。

即使上下文仍然存在,您也可能在序列化过程中遇到带有导航属性的循环。这是因为两个对象都持有对彼此的引用。考虑以下场景:

  • 您有一个名为 Country 的对象,其中包含一个名为 States 的延迟加载属性。
  • 序列化程序尝试序列化Country 类型的对象。
  • 它读取States 集合。
  • 它尝试序列化每个State 类型的对象。
  • 它读取Country 类型的属性。
  • 它尝试序列化Country 类型的对象。
  • 它读取States 集合。
  • 它尝试序列化每个State 类型的对象。
  • 它读取Country 类型的属性。
  • 它读取States 集合。
  • 它尝试序列化每个State 类型的对象。
  • 它读取Country 类型的属性。
  • 它读取States 集合。
  • 它尝试序列化每个State 类型的对象。
  • 它读取Country 类型的属性。
  • ....(无限循环,嗯,至少在您用完堆栈帧之前)。

或者,您可以创建一个自定义序列化程序,以避免导航属性的陷阱,但这可能比它的价值更多。这种方法最适合序列化版本与对象显着不同的情况。

这就是您最好使用数据传输对象 (DTO) 的原因。将数据映射到该对象并通过网络发送。如果您使结构尽可能相似,那么有些组件可以为您进行映射。

查看 AutoMapper:http://automapper.org/

【讨论】:

  • @Jaun 感谢您的回答。如果没有 DTO,我们可以做同样的工作吗?
  • @Umer:我扩展了我的答案以帮助您理解。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多