前言
在演示Demo、數據庫脫敏、性能測試中,有時需要生成大量隨機數據。Bogus就是.NET中優秀的高性能、合理、支持多語言的隨機數據生成庫。
Bogus的Github鏈接:https://github.com/bchavez/Bogus,圖標如下:
安裝Bogus
目前Bogus最新版是28.0.2,本文演示基本該版本,不保證官方以后會不會修改本文的使用方式。
使用Powershell安裝:
PM> Install-Package Bogus -Version 28.0.2
或者使用PackageReference:
<PackageReference Include="Bogus" Version="28.0.2" />
使用Bogus
我的數據生成代碼如下(代碼使用LINQPad運行,可以幾乎復制到Visual Studio中運行,效果一樣,其中.Dump()是LINQPad特有方法):
void Main
{
var userGenerator = new Faker<User>
.RuleFor(x => x.Id, x => x.IndexFaker + 1)
.RuleFor(x => x.Gender, x => x.Person.Gender)
.RuleFor(x => x.FirstName, (x, u) => x.Name.FirstName(u.Gender))
.RuleFor(x => x.LastName, (x, u) => x.Name.LastName(u.Gender))
.RuleFor(x => x.Email, (x, u) => x.Internet.Email(u.FirstName, u.LastName))
.RuleFor(x => x.BirthDate, x => x.Person.DateOfBirth)
.RuleFor(x => x.Company, x => x.Person.Company.Name)
.RuleFor(x => x.Phone, x => x.Person.Phone)
.RuleFor(x => x.Website, x => x.Person.Website)
.RuleFor(x => x.SSN, x => x.Person.Ssn);
userGenerator.GenerateForever.Take(10).Dump;
}
class User
{
public int Id { get; set; }
public Bogus.DataSets.Name.Gender Gender { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public DateTime BirthDate { get; set; }
public string Company { get; set; }
public string Phone { get; set; }
public string Website { get; set; }
public string SSN { get; set; }
}
生成的數據如圖所示:
注意細節,姓名FirstName/LastName是會根據性別Gender來隨機生成的,然后郵箱Email字段也會根據FirstName/LastName來相應地生成,并非完全隨機,毫無規律。這些規則是通過.RuleFor第二個回調的第二個字段來決定的:
.RuleFor(x => x.FirstName, (x, u) => x.Name.FirstName(u.Gender)) // 根據Gender生成FirstName
.RuleFor(x => x.LastName, (x, u) => x.Name.LastName(u.Gender)) // 根據Gender生成LastName
.RuleFor(x => x.Email, (x, u) => x.Internet.Email(u.FirstName, u.LastName)) // 根據姓名生成郵箱
最后的.GenerateForever返回了一個IEnumerable<User>,是一個狀態機,可以永久生成數據。
Bogus也提供了一次性生成緩存數據的方法:List<User> Generate(int count)。但由于我可能將這些數據做今后博客文章的性能測試原始數據,數據量可能會非常大,如果將這些數據緩存起來將非常浪費內存,并且影響性能。因此本例中我使用GenerateForever來生成原始數據。
通過.NET Core 3.0最新提供的System.Text.Json里面的JsonSerializer和Utf8JsonWriter,我可能以極其高效的方法將這些測試數據序列化為JSON,然后保存到磁盤中:
string path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"test-data.json";
using var file = File.Create(path);
using var writer = new Utf8JsonWriter(file, new JsonWriterOptions { Indented = true });
var data = userGenerator.GenerateForever.Take(6_0000);
JsonSerializer.Serialize(writer, data);
Process.Start("explorer", @$"/select, ""{path}""".Dump); // 資源管理器打開test-data.json文件夾
演示和下載
最后示例數據如下:
一共6萬條數據,每條數據有10個字段,test-data.json共19,166 KB。
可以用如下代碼將這6萬條數據加載到.NET內存:
void Main
{
string path = @"C:UserssdflyDesktoptest-datatest-data.json";
byte bytes = File.ReadAllBytes(path);
var users = JsonSerializer.Deserialize<List<User>>(bytes);
// 數據分析演示
users.GroupBy(x => x.Email[x.Email.IndexOf('@')..])
.Select(x => new { Host = x.Key, Count = x.Count })
.Dump;
}
class User
{
public int Id { get; set; }
public int Gender { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public DateTime BirthDate { get; set; }
public string Company { get; set; }
public string Phone { get; set; }
public string Website { get; set; }
public string SSN { get; set; }
}
結果如下:
所有郵件都是hotmail.com/gmail.com/yahoo.com三種郵箱的均勻分布,每種大約都在20000左右。
我計劃今后如需要做性能測試或者演示,將使用該文件作為基準數據,已經上傳到Github,該文件可以從這里下載:https://github.com/sdcb/blog-data/tree/master/2019/20190821-generate-lorem-data。
出處:微信公眾號【DotNet騷操作】
原文鏈接:https://www.cnblogs.com/sdflysha/p/20190821-generate-lorem-data.html