webAPI + EF5 dbset包含即使在visual studio中重新启动webAPI项目后也不在DB中的本地实体

时间:2013-05-31 12:12:38

标签: asp.net-web-api entity-framework-5

我一直在学习WebAPI + EF5,并基于此创建了我的第一个项目。

我在数据库中有一个表,其中包含ID,NAME,DESCRIPTION列,NAME列上有一个约束,以确保NAME对所有记录都是唯一的。

当我POST通过WebAPI项目(在Visual Studio中的调试中运行)向数据库说十个实体时,十个项目出现在物理数据库中 - 很酷。

如果我在webAPI控制器上调用GET,并检查dbset.Local,我会看到我发布的10个项目,这是完美的。

问题是,如果我在visual studio中停止WebAPI项目,在SQL管理工作室中打开数据库并删除物理行(代表我上面发布的10个项目),然后在visual studio中重新启动webAPI的调试。如果我执行GET请求(通过fiddler)并通过contoler的get方法中的断点检查dbset,我发现10个项目仍然在dbset.Local属性中,即使底层没有项目D B。如果我允许GET有效地完成调用dbset.ToList(),我得到一个空的结果集。

如果我重新发布相同的10个项目,则10个项目再次成功到达数据库,但现在dbset.Local在其本地集合中有20个项目!?

重新启动WebAPI项目后,为什么dbset.Local不为空,我可以停止调试去咖啡重启调试和dbset.Local集合中还有20个项目吗?这是我遇到的缓存问题吗?我在项目启动代码中需要做些什么,每次在Visual Studio中重新启动项目时都要处理这个以清除dbset.Local?

为什么dbset.Local不遵守在DB中设置的唯一名称的约束,并允许重复的条目进入dbset.Local集合,如果它没有抛出错误?

1 个答案:

答案 0 :(得分:1)

  

问题是如果我在visual studio中停止WebAPI项目......

如果您在ASP.NET中托管了WebAPI(Visual Studio中的标准WebAPI项目将创建这样的项目类型),则停止调试器实际上不会停止正在运行您的应用程序的进程,但它只会分离来自该应用程序的调试器。正在运行的进程是 - 例如,如果您使用IIS Express作为开发测试服务器 - Web服务器的工作进程,它将保持活动状态。 (它通常在Windows屏幕右下角的系统托盘中有一个小图标。您可以在那里停止该过程,然后该过程“真正”被杀死。)

  

...在SQL管理工作室中打开数据库并删除物理行   (代表我在上面发布的10个项目)......

DbSet<T>.Local是内存中的集合。它没有“看到”您在EF上下文之外的另一个进程(SSMS)中删除了数据库中的行。

  

...然后在visual studio中重新启动webAPI的调试。

如果提到的工作进程仍在运行,则重新启动调试器将无法启动新进程,但调试器附加到现有进程。这个过程中的一切仍然存在。

  

如果我执行GET请求(通过fiddler)并通过中断检查dbset   指向contoler的get方法,我发现有10个项目   仍然在dbset.Local属性中,即使没有项目   在基础数据库中。

因为检查或迭代DbSet<T>.Local或调用DbSet<T>.Local.ToList()没有运行数据库查询,所以它不会注意到DB表是空的。它只返回内存中的旧数据。

  

如果我允许GET有效地调用dbset.ToList()我   得到一个空的结果集。

由于DbSet<T>.ToList()实际上 运行数据库查询,因此会发现该表为空并将结果返回给您。

  

如果我重新发布相同的10个项目,则10个项目成功到达   再次使用DB,但现在dbset.Local在其Local中有20个项目   集合!?

因为DbSet<T>.Local仍然在内存中有旧的结果。虽然您之前对数据库的DbSet<T>.ToList()查询返回了一个空列表以提供正确的查询结果,但这并不意味着它清除了Local集合。如果它在数据库中找到了一个新实体(具有新的键值),则该实体将被添加到Local集合中(然后显示11个项目)。但查询永远不会从Local中删除项目。

  

重新启动WebAPI项目后,为什么dbset.Local不为空,我   可以停止调试去咖啡重启调试和   dbset.Local集合中还有20个项目吗?

尝试10次咖啡:)工作人员进程可能会在较长时间不活动后自动关闭。我不确定它需要多长时间以及它是否会在IIS Express中发生。

  

这是我遇到的缓存问题吗?有什么我需要的   在我的项目启动代码中,要处理这个以清除dbset.Local   每次在visual studio中重新启动项目?

是的,它(可能)是一个非常大的问题,因为Local集合中缓存的那些实体表明您正在多个Web请求中重用相同的上下文实例。当您依赖Local以及许多其他问题和异常时(例如,当您附加具有相同键的实体(如已在Local中的实体等)时,这可能会导致错误的结果。) 。这通常是最佳实践,建议在Web请求开始时创建新的上下文实例,在处理此单个请求期间使用它,然后在请求结束时将其处理。处置上下文将释放对象以进行垃圾回收。下一个请求时,新上下文实例的Local个集合将为空。 (这个以及怎么做(每个控制器,手动,依赖注入等)本身就是一个特殊的主题。尝试谷歌搜索“每个请求的实体框架上下文”或类似的关键字开始。)

  

为什么dbset.Local不遵守唯一名称的约束   在DB中设置并允许重复条目进入dbset.Local   收集,它不应该抛出错误吗?

实体框架不支持唯一约束(主键的唯一性除外),即它只是对数据库中的唯一索引一无所知。