概述: 我们需要在 SQL Server 数据库中创建 100 万个虚拟产品数据,这些数据可用于开发或性能测试。项目该项目是使用 .NET 6.0 作为框架的控制台应用程序。项目名称为 InsertMillionRecords我们将使用Bogus软件包来生成随机产品数据。我们使用 Entity Framework Core 作为数据访问层。产品型号为了对数据库中的 Products 表进行建模,我们需要创建 Product 类:public class Product { public int Id { get; set; } public string Code { get;
我们需要在 SQL Server 数据库中创建 100 万个虚拟产品数据,这些数据可用于开发或性能测试。
项目
该项目是使用 .NET 6.0 作为框架的控制台应用程序。
项目名称为 InsertMillionRecords
我们将使用Bogus软件包来生成随机产品数据。
我们使用 Entity Framework Core 作为数据访问层。
产品型号
为了对数据库中的 Products 表进行建模,我们需要创建 Product 类:
public classProduct
{
publicint Id { get; set; }
publicstring Code { get; set; }
publicstring Description { get; set; }
publicstring Category { get; set; }
publicdecimal Price { get; set; }
}
实体框架数据上下文
接下来,我们创建 Entity Framework 数据上下文类:
usingMicrosoft.EntityFrameworkCore;
namespaceInsertMillionRecords;
public classDataContext : DbContext
{
publicDataContext(DbContextOptions<DataContext> options) : base(options)
{
}
publicDbSet<Product> Products { get; set; }
}
Program.cs文件
初始化数据上下文
首先,我们需要初始化数据上下文:
var connectionString = "Data Source=localhost; Initial Catalog=Product; Integrated Security=True";
var contextOptionsBuilder = newDbContextOptionsBuilder<DataContext>();
contextOptionsBuilder.UseSqlServer(connectionString);
var context = newDataContext(contextOptionsBuilder.Options);
我们通过对连接字符串进行硬编码,使事情变得更简单。不用担心!
创建数据库
每次运行脚本时,我们都需要确保重新创建数据库。
await context.Database.EnsureDeletedAsync();
await context.Database.EnsureCreatedAsync();
设置 Bogus Faker 类
首先,我们初始化 Faker<Product> 对象。
接下来,我们使用该方法来设置 Product 类的每个属性。RuleFor()
自我解释的代码:
var faker = newFaker<Product>();
faker.RuleFor(p => p.Code, f => f.Commerce.Ean13());
faker.RuleFor(p => p.Description, f => f.Commerce.ProductName());
faker.RuleFor(p => p.Category, f => f.Commerce.Categories(1)[0]);
faker.RuleFor(p => p.Price, f => f.Random.Decimal(1, 1000));
生成 100 万个虚拟产品数据
var products = faker.Generate(1000000);
该变量现在包含 100 万个产品数据!products
创建 10 批插入
如果我们一次插入 100 万条记录,则可能会发生超时。
因此,我们将该过程分为 10 批。每批一次插入 100K 条记录。
var batches = products
.Select((p, i) => (Product: p, Index: i))
.GroupBy(x => x.Index / 100_000)
.Select(g => g.Select(x => x.Product).ToList())
.ToList();
将每个批次插入数据库
var count = 0;
foreach (var batch in batches)
{
batchCount++;
Console.WriteLine($"Inserting batch {count} of {batches.Count}...");
await context.Products.AddRangeAsync(batch);
await context.SaveChangesAsync();
}
Program.cs文件的完整代码:
usingBogus;
usingInsertMillionRecords;
usingMicrosoft.EntityFrameworkCore;
usingSystem.Diagnostics;
// initialize data context
var connectionString = "Data Source=localhost; Initial Catalog=Product; Integrated Security=True";
var contextOptionsBuilder = newDbContextOptionsBuilder<DataContext>();
contextOptionsBuilder.UseSqlServer(connectionString);
var context = newDataContext(contextOptionsBuilder.Options);
// create database
await context.Database.EnsureDeletedAsync();
await context.Database.EnsureCreatedAsync();
// setup bogus faker
var faker = newFaker<Product>();
faker.RuleFor(p => p.Code, f => f.Commerce.Ean13());
faker.RuleFor(p => p.Description, f => f.Commerce.ProductName());
faker.RuleFor(p => p.Category, f => f.Commerce.Categories(1)[0]);
faker.RuleFor(p => p.Price, f => f.Random.Decimal(1, 1000));
// generate 1 million products
var products = faker.Generate(1000000);
var batches = products
.Select((p, i) => (Product: p, Index: i))
.GroupBy(x => x.Index / 100000)
.Select(g => g.Select(x => x.Product).ToList())
.ToList();
// insert batches
var stopwatch = newStopwatch();
stopwatch.Start();
var count = 0;
foreach (var batch in batches)
{
count++;
Console.WriteLine($"Inserting batch {count} of {batches.Count}...");
await context.Products.AddRangeAsync(batch);
await context.SaveChangesAsync();
}
stopwatch.Stop();
Console.WriteLine($"Elapsed time: {stopwatch.Elapsed}");
Console.WriteLine("Press any key to exit...");
运行应用程序
现在,让我们运行应用程序。我们可以使用_释放_模式来加快该过程。
在我的机器上花了 1 分 9 秒:
现在,我们在 Products 表中有 100 万条记录:
我计划使用这些虚拟数据来测试 SQL Server 中的全文搜索功能。