U:调整所有代码格式

This commit is contained in:
jimmy committed 2025-12-30 09:17:25 +08:00
1 parent d133bacf55
commit 155b67e831
342 files changed
+9431 -9868

No files matched your search

+5 -7
View File
@@ -53,9 +53,9 @@ public class _00_QuickStart
{
var builder = new DataContextBuilder<TestDbContext>();
builder.UseInMemoryDatabase($"AuditDemo_{Guid.NewGuid()}")
.UseAudit(true) // 启用审计
.UseSoftDelete(true) // 启用软删除
.UseCurrentUser("admin"); // 设置当前用户
.UseAudit(true) // 启用审计
.UseSoftDelete(true) // 启用软删除
.UseCurrentUser("admin"); // 设置当前用户
using var db = builder.Build();
var repo = db.Repository<Product>();
@@ -96,15 +96,13 @@ public class _00_QuickStart
var repo = db.Repository<Product>();
// 添加测试数据
for (int i = 1; i <= 25; i++)
{
for (var i = 1; i <= 25; i++)
await repo.AddAsync(new Product
{
Name = $"产品{i}",
Price = i * 10m,
Stock = i
});
}
await db.SaveChangesAsync();
// 分页查询:第2页,每页10条
@@ -181,4 +179,4 @@ public class _00_QuickStart
Assert.AreEqual(1, count);
Console.WriteLine($"✓ 可以直接使用 EF Core,完全兼容!");
}
}
}
+9 -9
View File
@@ -69,12 +69,12 @@ public class _01_BasicUsageTests
// 链式配置所有功能
builder.UseInMemoryDatabase("FullConfigDemo")
.UseAudit(true) // 启用审计功能
.UseSoftDelete(true) // 启用软删除功能
.UseAutoMigration(true) // 启动时自动迁移数据库
.UseCurrentUser("admin") // 设置当前用户(用于审计)
.EnableDetailedErrors(true) // 启用详细错误信息
.EnableSensitiveDataLogging(true); // 启用敏感数据日志(仅开发环境)
.UseAudit(true) // 启用审计功能
.UseSoftDelete(true) // 启用软删除功能
.UseAutoMigration(true) // 启动时自动迁移数据库
.UseCurrentUser("admin") // 设置当前用户(用于审计)
.EnableDetailedErrors(true) // 启用详细错误信息
.EnableSensitiveDataLogging(true); // 启用敏感数据日志(仅开发环境)
using var db = builder.Build();
@@ -126,8 +126,8 @@ public class _01_BasicUsageTests
// 只启用审计,不启用软删除
builder.UseInMemoryDatabase("SelectiveDemo")
.UseAudit(true) // 启用审计
.UseSoftDelete(false); // 不启用软删除
.UseAudit(true) // 启用审计
.UseSoftDelete(false); // 不启用软删除
using var db = builder.Build();
@@ -269,4 +269,4 @@ public class _01_BasicUsageTests
builder.UseInMemoryDatabase($"TestDb_{Guid.NewGuid()}");
return builder.Build();
}
}
}
+16 -40
View File
@@ -89,10 +89,7 @@ public class _02_RepositoryCRUDTests
await _db.SaveChangesAsync();
Console.WriteLine($"✓ 成功添加 {products.Count} 个产品");
foreach (var product in products)
{
Console.WriteLine($" - {product.Name}: {product.Price:C}");
}
foreach (var product in products) Console.WriteLine($" - {product.Name}: {product.Price:C}");
// 验证
var allProducts = await repo.GetAllAsync();
@@ -146,10 +143,7 @@ public class _02_RepositoryCRUDTests
Assert.AreEqual(3, allProducts.Count);
Console.WriteLine($"✓ 获取所有数据成功,共 {allProducts.Count} 条");
foreach (var p in allProducts)
{
Console.WriteLine($" - {p.Name}: {p.Price:C}");
}
foreach (var p in allProducts) Console.WriteLine($" - {p.Name}: {p.Price:C}");
}
/// <summary>
@@ -174,10 +168,7 @@ public class _02_RepositoryCRUDTests
Assert.AreEqual(2, appleProducts.Count);
Console.WriteLine("✓ 条件查询成功,找到包含'苹果'的产品:");
foreach (var p in appleProducts)
{
Console.WriteLine($" - {p.Name}: {p.Price:C}");
}
foreach (var p in appleProducts) Console.WriteLine($" - {p.Name}: {p.Price:C}");
}
/// <summary>
@@ -265,25 +256,23 @@ public class _02_RepositoryCRUDTests
await _db.SaveChangesAsync();
// 获取可查询对象,进行复杂查询
var query = repo.Query(trackChanges: false); // trackChanges: false 提升查询性能
var query = repo.Query(false); // trackChanges: false 提升查询性能
var result = await query
.Where(p => p.Price > 2000) // 价格大于2000
.OrderByDescending(p => p.Price) // 按价格降序
.Select(p => new // 投影到匿名类型
.Where(p => p.Price > 2000) // 价格大于2000
.OrderByDescending(p => p.Price) // 按价格降序
.Select(p => new // 投影到匿名类型
{
p.Name,
p.Price,
p.Stock,
TotalValue = p.Price * p.Stock // 计算总价值
TotalValue = p.Price * p.Stock // 计算总价值
})
.ToListAsync();
Console.WriteLine("✓ 复杂查询成功,价格>2000的产品(按价格降序):");
foreach (var item in result)
{
Console.WriteLine($" - {item.Name}: {item.Price:C} x {item.Stock} = {item.TotalValue:C}");
}
Assert.AreEqual(3, result.Count);
}
@@ -345,19 +334,13 @@ public class _02_RepositoryCRUDTests
await _db.SaveChangesAsync();
// 批量涨价 10%
foreach (var product in products)
{
product.Price *= 1.10m;
}
foreach (var product in products) product.Price *= 1.10m;
repo.UpdateRange(products);
await _db.SaveChangesAsync();
Console.WriteLine("✓ 批量涨价 10% 成功:");
var updatedProducts = await repo.GetAllAsync();
foreach (var p in updatedProducts)
{
Console.WriteLine($" - {p.Name}: {p.Price:C}");
}
foreach (var p in updatedProducts) Console.WriteLine($" - {p.Name}: {p.Price:C}");
// 验证
Assert.AreEqual(110m, updatedProducts[0].Price);
@@ -377,7 +360,7 @@ public class _02_RepositoryCRUDTests
[TestMethod]
public async Task Demo_DeleteEntity()
{
var repo = _db.Repository<Category>(); // Category 没有软删除,是真实删除
var repo = _db.Repository<Category>(); // Category 没有软删除,是真实删除
// 添加分类
var category = new Category { Name = "测试分类" };
@@ -483,10 +466,7 @@ public class _02_RepositoryCRUDTests
.ToListAsync();
Console.WriteLine("✓ 按价格升序:");
foreach (var p in ascProducts)
{
Console.WriteLine($" - {p.Name}: {p.Price:C}");
}
foreach (var p in ascProducts) Console.WriteLine($" - {p.Name}: {p.Price:C}");
// 按价格降序
var descProducts = await repo.Query()
@@ -494,10 +474,7 @@ public class _02_RepositoryCRUDTests
.ToListAsync();
Console.WriteLine("✓ 按价格降序:");
foreach (var p in descProducts)
{
Console.WriteLine($" - {p.Name}: {p.Price:C}");
}
foreach (var p in descProducts) Console.WriteLine($" - {p.Name}: {p.Price:C}");
Assert.AreEqual("A产品", ascProducts[0].Name);
Assert.AreEqual("C产品", descProducts[0].Name);
@@ -537,12 +514,11 @@ public class _02_RepositoryCRUDTests
Console.WriteLine("✓ 按价格区间分组统计:");
foreach (var group in priceGroups)
{
Console.WriteLine($" - {group.PriceRange}: {group.Count}个产品, 平均价格 {group.AvgPrice:C}, 总库存 {group.TotalStock}");
}
Console.WriteLine(
$" - {group.PriceRange}: {group.Count}个产品, 平均价格 {group.AvgPrice:C}, 总库存 {group.TotalStock}");
Assert.AreEqual(3, priceGroups.Count);
}
#endregion
}
}
+17 -17
View File
@@ -27,8 +27,8 @@ public class _03_AuditFeatureTests
// 创建启用审计功能的 DataContext
var builder = new DataContextBuilder<TestDbContext>();
builder.UseInMemoryDatabase($"AuditCreateDemo_{Guid.NewGuid()}")
.UseAudit(true) // 启用审计
.UseCurrentUser("zhang.san"); // 设置当前用户
.UseAudit(true) // 启用审计
.UseCurrentUser("zhang.san"); // 设置当前用户
using var db = builder.Build();
var repo = db.Repository<Product>();
@@ -49,7 +49,7 @@ public class _03_AuditFeatureTests
Console.WriteLine($" CreatedBy: {product.CreatedBy ?? "(null)"}");
await repo.AddAsync(product);
await db.SaveChangesAsync(); // SaveChanges 时自动填充审计信息
await db.SaveChangesAsync(); // SaveChanges 时自动填充审计信息
var afterCreate = DateTime.UtcNow;
@@ -63,7 +63,7 @@ public class _03_AuditFeatureTests
// 验证
Assert.IsTrue(product.CreatedAt >= beforeCreate && product.CreatedAt <= afterCreate);
Assert.AreEqual("zhang.san", product.CreatedBy);
Assert.IsNull(product.UpdatedAt); // 创建时 UpdatedAt 为 null
Assert.IsNull(product.UpdatedAt); // 创建时 UpdatedAt 为 null
Assert.IsNull(product.UpdatedBy);
}
@@ -108,7 +108,7 @@ public class _03_AuditFeatureTests
product.Name = "更新后的产品";
product.Price = 200m;
repo.Update(product);
await db.SaveChangesAsync(); // SaveChanges 时自动填充 UpdatedAt 和 UpdatedBy
await db.SaveChangesAsync(); // SaveChanges 时自动填充 UpdatedAt 和 UpdatedBy
Console.WriteLine("\n更新后的审计信息:");
Console.WriteLine($" CreatedBy: {product.CreatedBy} (保持不变)");
@@ -117,11 +117,11 @@ public class _03_AuditFeatureTests
Console.WriteLine($" ✓ UpdatedAt: {product.UpdatedAt:yyyy-MM-dd HH:mm:ss}");
// 验证
Assert.AreEqual(createdBy, product.CreatedBy); // 创建人不变
Assert.AreEqual(createdAt, product.CreatedAt); // 创建时间不变
Assert.AreEqual("editor", product.UpdatedBy); // 更新人是新用户
Assert.AreEqual(createdBy, product.CreatedBy); // 创建人不变
Assert.AreEqual(createdAt, product.CreatedAt); // 创建时间不变
Assert.AreEqual("editor", product.UpdatedBy); // 更新人是新用户
Assert.IsNotNull(product.UpdatedAt);
Assert.IsTrue(product.UpdatedAt > product.CreatedAt); // 更新时间晚于创建时间
Assert.IsTrue(product.UpdatedAt > product.CreatedAt); // 更新时间晚于创建时间
}
/// <summary>
@@ -167,9 +167,9 @@ public class _03_AuditFeatureTests
Console.WriteLine($"第2次更新: {product.UpdatedBy} 于 {product.UpdatedAt:HH:mm:ss}");
// 验证
Assert.AreEqual("user1", product.CreatedBy); // 创建人始终不变
Assert.AreEqual("user3", product.UpdatedBy); // 最后更新人
Assert.IsTrue(product.UpdatedAt > firstUpdateTime); // 更新时间在变化
Assert.AreEqual("user1", product.CreatedBy); // 创建人始终不变
Assert.AreEqual("user3", product.UpdatedBy); // 最后更新人
Assert.IsTrue(product.UpdatedAt > firstUpdateTime); // 更新时间在变化
}
/// <summary>
@@ -215,8 +215,8 @@ public class _03_AuditFeatureTests
await db.SaveChangesAsync();
Console.WriteLine($"✓ 更新人: {product.UpdatedBy}");
Assert.AreEqual("zhang.san", product.CreatedBy); // 创建人不变
Assert.AreEqual("li.si", product.UpdatedBy); // 更新人改变
Assert.AreEqual("zhang.san", product.CreatedBy); // 创建人不变
Assert.AreEqual("li.si", product.UpdatedBy); // 更新人改变
}
/// <summary>
@@ -263,7 +263,7 @@ public class _03_AuditFeatureTests
{
var builder = new DataContextBuilder<TestDbContext>();
builder.UseInMemoryDatabase($"NoAuditDemo_{Guid.NewGuid()}")
.UseAudit(true) // 即使启用了审计功能
.UseAudit(true) // 即使启用了审计功能
.UseCurrentUser("admin");
using var db = builder.Build();
@@ -290,7 +290,7 @@ public class _03_AuditFeatureTests
{
var builder = new DataContextBuilder<TestDbContext>();
builder.UseInMemoryDatabase($"DisableAuditDemo_{Guid.NewGuid()}")
.UseAudit(false) // 禁用审计功能
.UseAudit(false) // 禁用审计功能
.UseCurrentUser("admin");
using var db = builder.Build();
@@ -368,4 +368,4 @@ public class _03_AuditFeatureTests
Console.WriteLine($" - 谁最后修改:{product.UpdatedBy}");
Console.WriteLine($" - 何时修改:{product.UpdatedAt:yyyy-MM-dd HH:mm:ss}");
}
}
}
+7 -18
View File
@@ -29,7 +29,7 @@ public class _04_SoftDeleteTests
var builder = new DataContextBuilder<TestDbContext>();
builder.UseInMemoryDatabase($"SoftDeleteDemo_{Guid.NewGuid()}")
.UseAudit(true)
.UseSoftDelete(true) // 启用软删除
.UseSoftDelete(true) // 启用软删除
.UseCurrentUser("admin");
using var db = builder.Build();
@@ -71,7 +71,7 @@ public class _04_SoftDeleteTests
// 但数据仍在数据库中
var allIncludingDeleted = await db.Context.Set<Product>()
.IgnoreQueryFilters() // 忽略软删除过滤器
.IgnoreQueryFilters() // 忽略软删除过滤器
.Where(p => p.Id == productId)
.FirstOrDefaultAsync();
@@ -147,15 +147,13 @@ public class _04_SoftDeleteTests
var repo = db.Repository<Product>();
// 添加 5 个产品
for (int i = 1; i <= 5; i++)
{
for (var i = 1; i <= 5; i++)
await repo.AddAsync(new Product
{
Name = $"产品{i}",
Price = i * 100m,
Stock = i * 10
});
}
await db.SaveChangesAsync();
Console.WriteLine("✓ 创建了 5 个产品");
@@ -264,15 +262,13 @@ public class _04_SoftDeleteTests
// 添加多个产品
var products = new List<Product>();
for (int i = 1; i <= 10; i++)
{
for (var i = 1; i <= 10; i++)
products.Add(new Product
{
Name = $"产品{i}",
Price = i * 100m,
Stock = i * 10
});
}
await repo.AddRangeAsync(products);
await db.SaveChangesAsync();
@@ -290,10 +286,7 @@ public class _04_SoftDeleteTests
Console.WriteLine($"✓ 剩余可见产品: {remaining.Count} 个");
Assert.AreEqual(5, remaining.Count);
foreach (var p in expensiveProducts)
{
Assert.IsTrue(p.IsDeleted);
}
foreach (var p in expensiveProducts) Assert.IsTrue(p.IsDeleted);
}
/// <summary>
@@ -343,7 +336,7 @@ public class _04_SoftDeleteTests
{
var builder = new DataContextBuilder<TestDbContext>();
builder.UseInMemoryDatabase($"DisableSoftDelete_{Guid.NewGuid()}")
.UseSoftDelete(false) // 禁用软删除
.UseSoftDelete(false) // 禁用软删除
.UseCurrentUser("admin");
using var db = builder.Build();
@@ -371,12 +364,8 @@ public class _04_SoftDeleteTests
.FirstOrDefaultAsync(p => p.Id == productId);
if (found != null)
{
Console.WriteLine($" 结果:软删除 (IsDeleted={found.IsDeleted})");
}
else
{
Console.WriteLine($" 结果:物理删除");
}
}
}
}
+37 -47
View File
@@ -30,8 +30,7 @@ public class _05_PaginationTests
// 添加测试数据:100 个产品
var repo = _db.Repository<Product>();
var products = new List<Product>();
for (int i = 1; i <= 100; i++)
{
for (var i = 1; i <= 100; i++)
products.Add(new Product
{
Name = $"产品{i:D3}",
@@ -39,7 +38,6 @@ public class _05_PaginationTests
Stock = i * 5,
Description = i % 2 == 0 ? "热门产品" : "普通产品"
});
}
await repo.AddRangeAsync(products);
await _db.SaveChangesAsync();
@@ -62,8 +60,8 @@ public class _05_PaginationTests
// 查询第 1 页,每页 10 条
var page1 = await repo.GetPagedAsync(
page: 1,
pageSize: 10);
1,
10);
Console.WriteLine($"第 1 页:");
Console.WriteLine($" 当前页: {page1.PageIndex}");
@@ -83,10 +81,7 @@ public class _05_PaginationTests
Assert.IsTrue(page1.HasNextPage);
Console.WriteLine($"\n产品列表:");
foreach (var product in page1.Items)
{
Console.WriteLine($" - {product.Name}: {product.Price:C}");
}
foreach (var product in page1.Items) Console.WriteLine($" - {product.Name}: {product.Price:C}");
}
/// <summary>
@@ -96,8 +91,8 @@ public class _05_PaginationTests
public async Task Demo_IterateAllPages()
{
var repo = _db.Repository<Product>();
int pageSize = 15;
int currentPage = 1;
var pageSize = 15;
var currentPage = 1;
Console.WriteLine($"=== 遍历所有页(每页 {pageSize} 条)===\n");
@@ -107,7 +102,8 @@ public class _05_PaginationTests
pageResult = await repo.GetPagedAsync(currentPage, pageSize);
Console.WriteLine($"第 {currentPage} 页: {pageResult.Items.Count} 条记录");
Console.WriteLine($" 范围: {(currentPage - 1) * pageSize + 1} - {Math.Min(currentPage * pageSize, pageResult.TotalCount)}");
Console.WriteLine(
$" 范围: {(currentPage - 1) * pageSize + 1} - {Math.Min(currentPage * pageSize, pageResult.TotalCount)}");
// 处理当前页数据
foreach (var product in pageResult.Items)
@@ -116,11 +112,10 @@ public class _05_PaginationTests
}
currentPage++;
} while (pageResult.HasNextPage);
Console.WriteLine($"\n✓ 总共遍历了 {currentPage - 1} 页");
Assert.AreEqual(7, currentPage - 1); // 100 / 15 = 7 页
Assert.AreEqual(7, currentPage - 1); // 100 / 15 = 7 页
}
/// <summary>
@@ -133,9 +128,9 @@ public class _05_PaginationTests
// 查询价格 > 500 的产品,第 1 页,每页 10 条
var result = await repo.GetPagedAsync(
page: 1,
pageSize: 10,
predicate: p => p.Price > 500m);
1,
10,
p => p.Price > 500m);
Console.WriteLine($"查询条件: 价格 > 500");
Console.WriteLine($" 总记录数: {result.TotalCount}");
@@ -160,23 +155,18 @@ public class _05_PaginationTests
// 按价格降序排列
var result = await repo.GetPagedAsync(
page: 1,
pageSize: 10,
predicate: null,
orderBy: q => q.OrderByDescending(p => p.Price));
1,
10,
null,
q => q.OrderByDescending(p => p.Price));
Console.WriteLine($"排序: 按价格降序");
Console.WriteLine($"\n前 10 个最贵的产品:");
foreach (var product in result.Items)
{
Console.WriteLine($" - {product.Name}: {product.Price:C}");
}
foreach (var product in result.Items) Console.WriteLine($" - {product.Name}: {product.Price:C}");
// 验证排序
for (int i = 0; i < result.Items.Count - 1; i++)
{
for (var i = 0; i < result.Items.Count - 1; i++)
Assert.IsTrue(result.Items[i].Price >= result.Items[i + 1].Price);
}
}
/// <summary>
@@ -189,10 +179,10 @@ public class _05_PaginationTests
// 查询热门产品,价格 > 300,按库存降序,第 2 页,每页 5 条
var result = await repo.GetPagedAsync(
page: 2,
pageSize: 5,
predicate: p => p.Description == "热门产品" && p.Price > 300m,
orderBy: q => q.OrderByDescending(p => p.Stock));
2,
5,
p => p.Description == "热门产品" && p.Price > 300m,
q => q.OrderByDescending(p => p.Stock));
Console.WriteLine($"复杂查询:");
Console.WriteLine($" 条件: 热门产品 AND 价格>300");
@@ -234,8 +224,8 @@ public class _05_PaginationTests
Console.WriteLine($"有下一页: {result.HasNextPage}");
// 计算记录范围
int startIndex = (result.PageIndex - 1) * result.PageSize + 1;
int endIndex = Math.Min(result.PageIndex * result.PageSize, result.TotalCount);
var startIndex = (result.PageIndex - 1) * result.PageSize + 1;
var endIndex = Math.Min(result.PageIndex * result.PageSize, result.TotalCount);
Console.WriteLine($"\n记录范围: {startIndex} - {endIndex}");
// 验证
@@ -256,9 +246,9 @@ public class _05_PaginationTests
// 查询不存在的条件
var result = await repo.GetPagedAsync(
page: 1,
pageSize: 10,
predicate: p => p.Price > 99999m);
1,
10,
p => p.Price > 99999m);
Console.WriteLine($"查询不存在的记录:");
Console.WriteLine($" 总记录数: {result.TotalCount}");
@@ -306,9 +296,9 @@ public class _05_PaginationTests
var repo = _db.Repository<Product>();
// 模拟用户请求
int requestedPage = 3;
int pageSize = 20;
string? searchTerm = "产品0"; // 用户搜索
var requestedPage = 3;
var pageSize = 20;
var searchTerm = "产品0"; // 用户搜索
Console.WriteLine($"=== UI 分页场景 ===");
Console.WriteLine($"用户请求: 第 {requestedPage} 页, 每页 {pageSize} 条");
@@ -316,12 +306,12 @@ public class _05_PaginationTests
// 执行分页查询
var result = await repo.GetPagedAsync(
page: requestedPage,
pageSize: pageSize,
predicate: string.IsNullOrEmpty(searchTerm)
requestedPage,
pageSize,
string.IsNullOrEmpty(searchTerm)
? null
: p => p.Name.Contains(searchTerm),
orderBy: q => q.OrderBy(p => p.Name));
q => q.OrderBy(p => p.Name));
// 构建返回给前端的数据
var uiData = new
@@ -387,8 +377,8 @@ public class _05_PaginationTests
.OrderBy(p => p.Name);
// 手动实现分页逻辑
int page = 2;
int pageSize = 10;
var page = 2;
var pageSize = 10;
var totalCount = await query.CountAsync();
var items = await query
@@ -412,4 +402,4 @@ public class _05_PaginationTests
Console.WriteLine($"\n✓ 可以直接使用 IQueryable 和 PagedResult 进行自定义分页");
}
}
}
+5 -10
View File
@@ -118,10 +118,7 @@ public class _06_CustomEntityTests
// 列出所有地区
var allRegions = await regions.ToListAsync();
Console.WriteLine($"\n所有地区:");
foreach (var region in allRegions)
{
Console.WriteLine($" [{region.Code}] {region.Name}");
}
foreach (var region in allRegions) Console.WriteLine($" [{region.Code}] {region.Name}");
}
/// <summary>
@@ -155,7 +152,7 @@ public class _06_CustomEntityTests
foreach (var tag in tags)
{
Console.WriteLine($" ID: {tag.Id}, Name: {tag.Name}, Color: {tag.Color}");
Assert.IsTrue(tag.Id > 0); // 自增 Id
Assert.IsTrue(tag.Id > 0); // 自增 Id
}
// 查询
@@ -306,8 +303,7 @@ public class _06_CustomEntityTests
var repo = db.Repository<CustomProduct>();
// 添加测试数据
for (int i = 1; i <= 20; i++)
{
for (var i = 1; i <= 20; i++)
await repo.AddAsync(new CustomProduct
{
Id = Guid.NewGuid(),
@@ -315,7 +311,6 @@ public class _06_CustomEntityTests
Price = i * 100m,
CreatedDate = DateTime.UtcNow.AddDays(-i)
});
}
await db.SaveChangesAsync();
Console.WriteLine("=== 自定义实体的查询 ===\n");
@@ -326,7 +321,7 @@ public class _06_CustomEntityTests
// 2. 使用业务属性查询
var veryExpensive = await repo.Query()
.Where(p => p.IsExpensive) // 使用计算属性
.Where(p => p.IsExpensive) // 使用计算属性
.ToListAsync();
Console.WriteLine($"2. 使用 IsExpensive 属性: {veryExpensive.Count} 个");
@@ -382,4 +377,4 @@ public class _06_CustomEntityTests
Console.WriteLine(" 你可以完全自定义,仍然享受仓储模式的便利");
Console.WriteLine(" 灵活性和便利性可以兼得!");
}
}
}
+12 -19
View File
@@ -209,7 +209,7 @@ public class _07_EFCoreDirectUsageTests
var product3 = new Product { Name = "产品3", Price = 300m, Stock = 30 };
await productRepo.AddAsync(product2);
await productRepo.AddAsync(product3);
await db.SaveChangesAsync(); // 两个产品作为一个事务提交
await db.SaveChangesAsync(); // 两个产品作为一个事务提交
Console.WriteLine($" ✓ 隐式事务添加了 2 个产品");
@@ -233,15 +233,13 @@ public class _07_EFCoreDirectUsageTests
Console.WriteLine("1. 批量插入(推荐方式):");
var products = new List<Product>();
for (int i = 1; i <= 1000; i++)
{
for (var i = 1; i <= 1000; i++)
products.Add(new Product
{
Name = $"产品{i}",
Price = i * 10m,
Stock = i
});
}
var startTime = DateTime.UtcNow;
@@ -288,15 +286,13 @@ public class _07_EFCoreDirectUsageTests
var repo = db.Repository<Product>();
// 添加测试数据
for (int i = 1; i <= 100; i++)
{
for (var i = 1; i <= 100; i++)
await repo.AddAsync(new Product
{
Name = $"产品{i}",
Price = i * 10m,
Stock = i
});
}
await db.SaveChangesAsync();
Console.WriteLine("=== AsNoTracking 优化 ===\n");
@@ -310,14 +306,14 @@ public class _07_EFCoreDirectUsageTests
Console.WriteLine("\n2. AsNoTracking 查询(不跟踪):");
var untrackedProducts = await db.Context.Set<Product>()
.AsNoTracking() // 不跟踪实体变化
.AsNoTracking() // 不跟踪实体变化
.Take(10)
.ToListAsync();
Console.WriteLine($" ✓ 查询 {untrackedProducts.Count} 条,实体不被跟踪");
Console.WriteLine($" 适用于: 只读查询、数据展示");
Console.WriteLine("\n3. 仓储默认支持:");
var query = repo.Query(trackChanges: false); // 指定不跟踪
var query = repo.Query(false); // 指定不跟踪
var products = await query.Take(10).ToListAsync();
Console.WriteLine($" ✓ 仓储的 Query() 方法支持 trackChanges 参数");
@@ -354,21 +350,22 @@ public class _07_EFCoreDirectUsageTests
var entry = db.Context.Entry(product);
Console.WriteLine($"1. 新增状态:");
Console.WriteLine($" EntityState: {entry.State}"); // Added
Console.WriteLine($" EntityState: {entry.State}"); // Added
Assert.AreEqual(EntityState.Added, entry.State);
await db.SaveChangesAsync();
Console.WriteLine($"\n2. 保存后状态:");
Console.WriteLine($" EntityState: {entry.State}"); // Unchanged
Console.WriteLine($" EntityState: {entry.State}"); // Unchanged
Assert.AreEqual(EntityState.Unchanged, entry.State);
// 修改实体
product.Price = 200m;
Console.WriteLine($"\n3. 修改后状态:");
Console.WriteLine($" EntityState: {entry.State}"); // Modified
Console.WriteLine($" 修改的属性: {string.Join(", ", entry.Properties.Where(p => p.IsModified).Select(p => p.Metadata.Name))}");
Console.WriteLine($" EntityState: {entry.State}"); // Modified
Console.WriteLine(
$" 修改的属性: {string.Join(", ", entry.Properties.Where(p => p.IsModified).Select(p => p.Metadata.Name))}");
Assert.AreEqual(EntityState.Modified, entry.State);
// 查看原始值和当前值
@@ -396,8 +393,7 @@ public class _07_EFCoreDirectUsageTests
var repo = db.Repository<Product>();
// 添加测试数据
for (int i = 1; i <= 50; i++)
{
for (var i = 1; i <= 50; i++)
await repo.AddAsync(new Product
{
Name = $"产品{i}",
@@ -405,7 +401,6 @@ public class _07_EFCoreDirectUsageTests
Stock = i * 2,
Description = i % 2 == 0 ? "热门" : "普通"
});
}
await db.SaveChangesAsync();
Console.WriteLine("=== 高级查询技巧 ===\n");
@@ -439,9 +434,7 @@ public class _07_EFCoreDirectUsageTests
.ToListAsync();
foreach (var stat in groupStats)
{
Console.WriteLine($" {stat.Category}: {stat.Count}个, 均价 {stat.AvgPrice:C}, 最大库存 {stat.MaxStock}");
}
// 3. 子查询
Console.WriteLine("\n3. 子查询:");
@@ -493,4 +486,4 @@ public class _07_EFCoreDirectUsageTests
Console.WriteLine(" 两者可以自由组合使用,根据场景选择");
Console.WriteLine(" 底层完全共用同一个 DbContext,无缝协作");
}
}
}
+3 -3
View File
@@ -17,12 +17,12 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Sharp\Data\Data.csproj" />
<ProjectReference Include="..\..\src\Sharp\Common\Common.csproj" />
<ProjectReference Include="..\..\src\Sharp\Data\Data.csproj"/>
<ProjectReference Include="..\..\src\Sharp\Common\Common.csproj"/>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="9.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="9.0.0"/>
</ItemGroup>
</Project>
+20 -20
View File
@@ -6,17 +6,17 @@
## 测试文件说明
| 文件 | 说明 | 主要演示内容 |
|------|------|------------|
| `TestEntities.cs` | 实体定义演示 | 6种不同的实体定义方式 |
| `TestDbContext.cs` | DbContext 配置演示 | 如何配置各种实体 |
| `01_BasicUsageTests.cs` | 基础使用 | 3行代码快速开始、各种配置选项 |
| `02_RepositoryCRUDTests.cs` | 仓储 CRUD | 增删改查、批量操作、复杂查询 |
| `03_AuditFeatureTests.cs` | 审计功能 | 自动记录创建/修改信息 |
| `04_SoftDeleteTests.cs` | 软删除功能 | 逻辑删除 vs 物理删除 |
| `05_PaginationTests.cs` | 分页查询 | 各种分页场景 |
| `06_CustomEntityTests.cs` | 自定义实体 | 不使用基类的灵活方式 |
| `07_EFCoreDirectUsageTests.cs` | EF Core 直接使用 | 原生 SQL、事务、高级查询 |
| 文件 | 说明 | 主要演示内容 |
|--------------------------------|----------------|-----------------|
| `TestEntities.cs` | 实体定义演示 | 6种不同的实体定义方式 |
| `TestDbContext.cs` | DbContext 配置演示 | 如何配置各种实体 |
| `01_BasicUsageTests.cs` | 基础使用 | 3行代码快速开始、各种配置选项 |
| `02_RepositoryCRUDTests.cs` | 仓储 CRUD | 增删改查、批量操作、复杂查询 |
| `03_AuditFeatureTests.cs` | 审计功能 | 自动记录创建/修改信息 |
| `04_SoftDeleteTests.cs` | 软删除功能 | 逻辑删除 vs 物理删除 |
| `05_PaginationTests.cs` | 分页查询 | 各种分页场景 |
| `06_CustomEntityTests.cs` | 自定义实体 | 不使用基类的灵活方式 |
| `07_EFCoreDirectUsageTests.cs` | EF Core 直接使用 | 原生 SQL、事务、高级查询 |
## 运行测试
@@ -165,19 +165,19 @@ using (var dbB = CreateDataContext("userB"))
## 最佳实践
1. **根据需求选择实体定义方式**
- 需要审计+软删除:使用 `AuditableEntity`
- 只需要基础 CRUD:使用 `Entity` 或完全自定义
- 已有实体模型:保持原样,直接使用
- 需要审计+软删除:使用 `AuditableEntity`
- 只需要基础 CRUD:使用 `Entity` 或完全自定义
- 已有实体模型:保持原样,直接使用
2. **性能优化**
- 只读查询使用 `AsNoTracking()`
- 批量操作使用 `AddRange/UpdateRange/RemoveRange`
- 避免在循环中调用 `SaveChangesAsync`
- 只读查询使用 `AsNoTracking()`
- 批量操作使用 `AddRange/UpdateRange/RemoveRange`
- 避免在循环中调用 `SaveChangesAsync`
3. **灵活使用**
- 简单场景用仓储
- 复杂查询直接用 EF Core
- 两者可以无缝混用
- 简单场景用仓储
- 复杂查询直接用 EF Core
- 两者可以无缝混用
## 问题反馈
+1 -1
View File
@@ -180,4 +180,4 @@ public class TestDbContext : DbContext
entity.HasIndex(e => e.Email);
});
}
}
}
+1 -1
View File
@@ -156,4 +156,4 @@ public class Address
public string Country { get; set; } = string.Empty;
}
#endregion
#endregion