使用 Entity Framework Core 和 ThreadPool 而不达到最大 SQL Server 连接
Posted
技术标签:
【中文标题】使用 Entity Framework Core 和 ThreadPool 而不达到最大 SQL Server 连接【英文标题】:Use Entity Framework Core with ThreadPool without reaching maximum SQL Server connection 【发布时间】:2021-07-14 05:54:32 【问题描述】:我尝试向我的 SQL Server 插入大量数据而未达到最大连接数。
我已经尝试在我的连接字符串中最大化池大小,如下所示:
optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Echo;Max Pool Size=5000;Pooling=True;");
是否可以为每个线程使用一个连接?
这是我的代码
public static void GenerateMeridien()
List<Parallele> paralleleList = null;
using (var context = new EchoContext())
paralleleList = context.Paralleles.ToList();
foreach (Parallele parallele in paralleleList)
ThreadPool.QueueUserWorkItem(new WaitCallback(MeridienTaskCallback), parallele);
private static void MeridienTaskCallback(object paralleleObj)
Parallele parallele = (Parallele)paralleleObj;
// The context always reaches maximum connection because the garbage collector is not fast enough
using (var context = new EchoContext())
List<Square> squareList = SquareLogic.GenerateSquare(parallele);
context.Squares.AddRange(squareList);
context.SaveChanges();
Console.Write("*");
【问题讨论】:
正确使用IDisposable
(通常通过using
)否定“垃圾收集器未运行”。究竟是什么连接(暂时)泄漏?
请提供一些数字:数据量、频率等。
@tymtam 在他的回答中提到的问题是您的代码试图同时并行运行所有插入。解决方案是在任何时候简单地限制工人的数量。
顺便说一句,您根本没有理由使用多线程。如果你切换到异步/等待,你将能够运行这个“单线程/异步/并发”。
获取适当的 BulkCopy 库并在一批中插入所有内容。
【参考方案1】:
选项 A。并行工作,保存一次
每次计算后都需要保存吗?你可以并行计算并保存吗?
List<Parallele> paralleleList = null;
using (var context = new EchoContext())
paralleleList = context.Paralleles.ToList();
List<Square> squares = DoAllWorkInParallel(paralleleList);
// Save once:
using (var context = new EchoContext())
context.Squares.AddRange(squares);
context.SaveChanges();
选项 B. 一直保存
我认为你应该使用Parallel.ForEach
和MaxDegreeOfParallelism
或使用Task.WhenAll
。
Parallel.ForEach
例如:
public static async Task GenerateMeridien()
List<Parallele> paralleleList = null;
using (var context = new EchoContext())
paralleleList = context.Paralleles.ToList();
Parallel.ForEach(
source: paralleleList,
parallelOptions: new ParallelOptionsMaxDegreeOfParallelism = x,
body: parallele => Work(parallele));
private static void Work(Parallele parallele)
using (var context = new EchoContext())
List<Square> squareList = SquareLogic.GenerateSquare(parallele);
context.Squares.AddRange(squareList);
await context.SaveChanges();
Task.WhenAll
public static async Task GenerateMeridien()
List<Parallele> paralleleList = null;
using (var context = new EchoContext())
paralleleList = context.Paralleles.ToList();
var tasks = new List<Task>();
foreach (Parallele parallele in paralleleList)
tasks.Add(WorkAsync(parallele));
await Task.WhenAll(tasks.ToArray());
private static async Task WorkAsync(Parallele parallele)
using (var context = new EchoContext())
List<Square> squareList = SquareLogic.GenerateSquare(parallele);
context.Squares.AddRange(squareList);
await context.SaveChangesAsync();
【讨论】:
以上是关于使用 Entity Framework Core 和 ThreadPool 而不达到最大 SQL Server 连接的主要内容,如果未能解决你的问题,请参考以下文章
在 Entity Framework Core 中使用 [ComplexType]
在 Entity Framework Core 中使用 SQL 视图
使用 Entity Framework Core 更新相关数据