我已经做了很多搜索和试验,但一直无法找到解决这个问题的可行方法。
环境/工具
- 视觉工作室 2013
- C#
- 三层网络应用程序:
- 数据库层: SQL Server 2012
- 中间层: Entity Framework 6.* 使用 Database First,Web API 2.*
- 表示层: MVC 5 w/Razor、Bootstrap、jQuery 等。
背景
我正在为需要严格的三层架构的客户端构建一个 Web 应用程序。具体来说,表示层必须通过 Web 服务执行所有数据访问。表示层不能直接访问数据库。该应用程序允许一小部分付费员工管理人员、等候名单和他们正在等待的资源。根据需求,数据模型/数据库设计完全以人(用户表)为中心。
问题
当表示层请求某些东西时,比如资源,它至少与一个用户相关,而用户又与其他一些表相关,比如角色,这些表与更多用户相关,这些用户与更多角色和其他相关事物。关键是,当我查询 EF 想要引入的几乎整个数据库的任何内容时。
由于 EF 的默认延迟加载行为,这通常是可以的,但是当将任何对象序列化为 JSON 以返回到表示层时,Newtonsoft.Json 序列化程序会挂起很长时间,然后引发堆栈错误。
我试过的
这是我到目前为止所尝试的:
将 Newtonsoft 的 JSON 串行器 ReferenceLoopHandling 设置设置为 Ignore。没运气。这不是循环图问题,它只是引入的大量数据(有超过 20,000 个用户)。
清除/重置不需要的集合并将引用属性设置为 null。这显示了一些希望,但我无法绕过 Entity Framework 跟踪所有内容的愿望。
只需将导航属性设置为 null/clear 会导致这些更改在下一个 .SaveChanges() 上保存回数据库(注意:这是一个假设,但看起来很合理。如果有人知道不同,请说出来)。
分离实体会导致 EF 自动清除所有集合并将所有引用属性设置为 null,无论我是否想要它。
对所有内容使用 .AsNotTracking() 会引发一些关于不允许非跟踪实体具有导航属性的异常(我不记得确切的细节)。
使用 AutoMapper 制作对象图的副本,仅包括我指定的相关对象。这种方法基本上是有效的,但在(我相信)执行自动映射的过程中,所有导航属性都被访问,导致 EF 查询和解决它们。在一种情况下,这会在对 Web 服务的单个请求期间导致近 300,000 次数据库调用。
我在寻找什么
简而言之,之前有没有人必须解决这个问题并提出一个有效的解决方案?
缺乏这一点,任何关于至少在哪里寻找如何处理这个问题的指针都将不胜感激。
附加说明:当我写这篇文章时,我想到我可以将上面的第二项和第三项结合起来。换句话说,设置/清除导航属性,然后将图形自动映射到新对象,然后分离所有内容以使其不会被保存(或者可能将其包装在事务中并在最后回滚)。但是,如果有更优雅的解决方案,我宁愿使用它。
谢谢,戴夫