EntityFramework Core依赖注入上下文方式不同造成内存泄漏了解一下?
前言
这个问题从未遇见过,是一位前辈问我EF Core内存泄漏问题时我才去深入探讨这个问题,刚开始我比较惊讶,居然还有这种问题,然后就有了本文,直接拿前辈的示例代码并稍加修改成就了此文,希望对在自学EF Core过程中的童鞋能有些许帮助。
EntityFramework Core内存泄漏回顾
接下来我将用简单示例代码来还原整个造成EntityFramework Core内存泄漏的过程,同时在这个过程中您也可思考一下其中的原因和最终的结果是否一致。
public class TestA
{
public long Id { get; set; }
public string Name { get; set; }
}
public class EFCoreDbContext : DbContext
{
public EFCoreDbContext(DbContextOptions options)
: base(options)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("data source=WANGPENG;User Id=sa;Pwd=sa123;initial catalog=MemoryLeak;integrated security=True;MultipleActiveResultSets=True;");
base.OnConfiguring(optionsBuilder);
} public DbSet<TestA> TestA { get; set; }
}
public class TestUserCase
{
public void InvokeMethod(IServiceProvider serviceProvider)
{
EFCoreDbContext _context = null; if (_context == null)
{
_context = serviceProvider.GetRequiredService<EFCoreDbContext>();
} for (var i = ; i < ; i++)
{
var testA = _context.TestA.FirstOrDefault();
Console.WriteLine(i);
}
}
}
如上是整个示例代码,重头戏来了,接下来我们在控制台中来通过依赖注入上下文,并获取注入容器中的上下文并调用上述TestUserCase类中的方法,如下:
var services = new ServiceCollection(); services.AddDbContext<EFCoreDbContext>(options => options.UseSqlServer("data source=WANGPENG;User Id=sa;Pwd=sa123;initial catalog=MemoryLeak;integrated security=True;MultipleActiveResultSets=True;")); var serviceProvider = services.BuildServiceProvider(); for (int i = ; i < ; i++)
{
var test = new TestUserCase();
test.InvokeMethod(serviceProvider);
}
通过上述测试内存基本在15兆左右,当然根据机器配置不同最终得到的结果有所差异,但是内存基本没有什么大的波动,接下来我们来改造上述代码。上述我们将serviceProvider通过方法传递到TestUserCase中的InvokeMethod方法中,为了简便我们将获取到的serviceProvider改造成静态的,如下:
public static class ServiceLocator
{
private static IServiceCollection _services; public static IServiceProvider Instance
{
get
{
if (_services == null)
return null;
else
return _services.BuildServiceProvider();
}
} public static void Init(IServiceCollection services)
{
_services = services;
}
}
public class TestUserCase
{
public void InvokeMethod()
{
IServiceScope _serviceScope = null;
EFCoreDbContext _context = null;
if (_context == null)
{
_serviceScope = ServiceLocator.Instance.GetRequiredService<IServiceScopeFactory>().CreateScope();
_context = _serviceScope.ServiceProvider.GetRequiredService<EFCoreDbContext>();
} for (var i = ; i < ; i++)
{
var testA = _context.TestA.FirstOrDefault();
Console.WriteLine(i);
}
}
}
var services = new ServiceCollection(); services.AddDbContext<EFCoreDbContext>(options => options.UseSqlServer("data source=WANGPENG;User Id=sa;Pwd=sa123;initial catalog=MemoryLeak;integrated security=True;MultipleActiveResultSets=True;")); ServiceLocator.Init(services); for (int i = ; i < ; i++)
{
var test = new TestUserCase();
test.InvokeMethod();
}
如上我们通过ServiceLocator类来构建serviceProvider,并将返回serviceProvider赋值给静态变量,然后在我们调用的方法中直接获取容器中的上下文,这样就免去了传递的麻烦。
经过我们上述改造后最终运行内存达到了比较可怕的三百多兆,看来上下文压根就没进行GC,那我是不是改造成如下就可以了呢?
var scopeFactory = ServiceLocator.Instance.GetRequiredService<IServiceScopeFactory>(); using (var scope = scopeFactory.CreateScope())
using (var context = scope.ServiceProvider.GetRequiredService<EFCoreDbContext>())
{
for (var i = ; i < ; i++)
{
var testA = context.TestA.FirstOrDefault();
Console.WriteLine(i);
}
}
原以为是上下文没有及时得到释放而导致内存激增,但是看到上述结果依然一样没有任何改变,问题是不是到此就结束了呢?下面我们改变注入上下文的方式看看,如下:
var services = new ServiceCollection(); var options = new DbContextOptionsBuilder<EFCoreDbContext>()
.UseSqlServer("data source=WANGPENG;User Id=sa;Pwd=sa123;initial catalog=MemoryLeak;integrated security=True;MultipleActiveResultSets=True;")
.Options;
services.AddScoped(s => new EFCoreDbContext(options));
当我们改变了注入上下文方式后发现此时不会造成内存泄漏,也就是说上下文得到了GC,无论是我是否是手动释放上下文即通过Using包括或者不包括都不会出现内存泄漏问题。通过注入方式不同得到的结果截然不同,但是在我们的理解中通过AddDbContext注入上下文中的第二个参数是默认为Scope,那和我们通过AddScoped注入上下文应该是一样对不对,那为何结果又不同呢?岂不是冲突了吗?在Web不会出现这样的问题,未深入研究,我猜测其原因可能如下:
通过AddDbContext注入上下文只适用于Web应用程序即只对Web应用程序有效而对控制台程序可能无效,同时在Web应用程序中AddDbContext注入上下文和AddScoped注入上下文一致,而对于控制台程序存在不一致问题。一言以蔽之,在Web和Console中通过AddDbContext注入上下文可能存在处理机制不同。
总结
不知如上浅薄分析是否有漏洞或者说代码有错误的地方,期待看到本文的您能有更深入的见解可留下您的评论,如果结果是这样不建议在控制台中使用AddDbContext方法注入上下文。
EntityFramework Core依赖注入上下文方式不同造成内存泄漏了解一下?的更多相关文章
- Webservice WCF WebApi 前端数据可视化 前端数据可视化 C# asp.net PhoneGap html5 C# Where 网站分布式开发简介 EntityFramework Core依赖注入上下文方式不同造成内存泄漏了解一下? SQL Server之深入理解STUFF 你必须知道的EntityFramework 6.x和EntityFramework Cor
Webservice WCF WebApi 注明:改编加组合 在.net平台下,有大量的技术让你创建一个HTTP服务,像Web Service,WCF,现在又出了Web API.在.net平台下, ...
- .net core options 依赖注入的方式
options 依赖注入的方式 public class JwtSettingsOptions { public const string JwtSettings = "JwtSetting ...
- [译]ASP.NET Core依赖注入深入讨论
原文链接:ASP.NET Core Dependency Injection Deep Dive - Joonas W's blog 这篇文章我们来深入探讨ASP.NET Core.MVC Core中 ...
- ASP.NET Core依赖注入——依赖注入最佳实践
在这篇文章中,我们将深入研究.NET Core和ASP.NET Core MVC中的依赖注入,将介绍几乎所有可能的选项,依赖注入是ASP.Net Core的核心,我将分享在ASP.Net Core应用 ...
- Spring(八):Spring配置Bean(一)BeanFactory&ApplicationContext概述、依赖注入的方式、注入属性值细节
在Spring的IOC容器里配置Bean 配置Bean形式:基于xml文件方式.基于注解的方式 在xml文件中通过bean节点配置bean: <?xml version="1.0&qu ...
- 在WPF中使用依赖注入的方式创建视图
在WPF中使用依赖注入的方式创建视图 0x00 问题的产生 互联网时代桌面开发真是越来越少了,很多应用都转到了浏览器端和移动智能终端,相应的软件开发上的新技术应用到桌面开发的文章也很少.我之前主要做W ...
- # ASP.NET Core依赖注入解读&使用Autofac替代实现
标签: 依赖注入 Autofac ASPNETCore ASP.NET Core依赖注入解读&使用Autofac替代实现 1. 前言 2. ASP.NET Core 中的DI方式 3. Aut ...
- Spring学习(三)——Spring中的依赖注入的方式
[前面的话] Spring对我太重要了,做个关于web相关的项目都要使用Spring,每次去看Spring相关的知识,总是感觉一知半解,没有很好的系统去学习一下,现在抽点时间学习一下Spring.不知 ...
- net core 依赖注入问题
net core 依赖注入问题 最近.net core可以跨平台了,这是一个伟大的事情,为了可以赶上两年以后的跨平台部署大潮,我也加入到了学习之列.今天研究的是依赖注入,但是我发现一个问题,困扰我很久 ...
随机推荐
- 【.NET Core】ASP.NET Core之IdentityServer4(1):快速入门
[.NET Core]ASP.NET Core之IdentityServer4 本文中的IdentityServer4基于上节的jenkins 进行docker自动化部署. 使用了MariaDB,EF ...
- Commandline OpenVPN client on Mac OSX with macports
http://www.tuicool.com/articles/FjuyQj 注:文中有些内容做了修改,特别是那个配置文件,不能直接抄着用. Most people use TunnelBrick ...
- 循环神经网络(RNN)--学习笔记
一.基本概念 RNN针对的数据是时序数据.RNN它解决了前馈神经网络,无法体现数据时序关系的缺点.在RNN网络中,不仅同一个隐含层的节点可以相互连接,同时隐含层的输入不仅来源于输入层的输入还包括了上一 ...
- 如何使用php生成唯一ID的4种方法
php生成唯一ID的应用场景非常普遍,如临时缓存文件名称,临时变量,临时安全码等,uniqid()函数基于以微秒计的当前时间,生成一个唯一的 ID.由于生成唯一ID与微秒时间关联,因此ID的唯一性非常 ...
- 基于Microsoft Graph打造自己的Timeline应用
原文链接:https://github.com/chenxizhang/office365dev/blob/e9b5a59cb827841d36692cc4ec52c11d43062e04/docs/ ...
- (干货)微信小程序之转发好友
今天简单地说下微信小程序的转发功能,为什么要简单的说下呢,因为主要讲的就是转发给好友或者群组,还有一种是分享到朋友圈,这种就比较复杂一点了,先稍微透漏一点,分享到朋友圈主要是两种方法,一种是后台直接生 ...
- 易用性测试、本地化测试、部署测试、无障碍测试、回归测试、冒烟测试、A/B测试
1.易用性定义: 易用性测试是指测试用户使用软件时是否感觉方便,是否能保证用户使用的测试类型2.本地化测试: ·定义:针对软件的本地化版本实施的针对性测试 ·测试内容: (1)语言,书写习惯 (2)时 ...
- C# 使用 SmtpClient.SendAsync 方法发送邮件失败,总是返回 Cancelled
问题: 调用 SmtpClient.SendAsync,在 SendCompleted 的回调函数里面总是获取到 e.Cancelled 为 true. 后来测试了一下,相同的代码,只是把 SmtpC ...
- SpringMVC中的文件上传
1. 配置图片服务器 一般图片会单独保存在图片服务器上, 本文为简化处理, 在Tomcat中配置一个路劲用于专门存放图片 在tomcat上配置图片虚拟目录,在tomcat下conf/server.xm ...
- PAT1007:Maximum Subsequence Sum
1007. Maximum Subsequence Sum (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Y ...