A:增加数据库配置和使用
This commit is contained in:
1 parent
53d1dd2dbf
commit
f7660c49e8
86 files changed
+7401
-271
No files matched your search
@@ -0,0 +1,371 @@
|
||||
using Sharp.Data;
|
||||
using Sharp.Data.Context;
|
||||
|
||||
namespace Data.Test;
|
||||
|
||||
/// <summary>
|
||||
/// 演示 03: 审计功能
|
||||
///
|
||||
/// 本测试类演示:
|
||||
/// 1. 如何启用审计功能
|
||||
/// 2. 创建时自动记录 CreatedAt 和 CreatedBy
|
||||
/// 3. 更新时自动记录 UpdatedAt 和 UpdatedBy
|
||||
/// 4. 如何设置当前用户
|
||||
/// 5. 审计功能对不同实体的影响
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public class _03_AuditFeatureTests
|
||||
{
|
||||
/// <summary>
|
||||
/// 演示: 基础审计功能 - 创建时自动记录
|
||||
///
|
||||
/// 使用 AuditableEntity 基类的实体会自动记录审计信息
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public async Task Demo_AuditOnCreate()
|
||||
{
|
||||
// 创建启用审计功能的 DataContext
|
||||
var builder = new DataContextBuilder<TestDbContext>();
|
||||
builder.UseInMemoryDatabase($"AuditCreateDemo_{Guid.NewGuid()}")
|
||||
.UseAudit(true) // 启用审计
|
||||
.UseCurrentUser("zhang.san"); // 设置当前用户
|
||||
|
||||
using var db = builder.Build();
|
||||
var repo = db.Repository<Product>();
|
||||
|
||||
var beforeCreate = DateTime.UtcNow;
|
||||
|
||||
// 创建产品
|
||||
var product = new Product
|
||||
{
|
||||
Name = "测试产品",
|
||||
Price = 99.00m,
|
||||
Stock = 10
|
||||
};
|
||||
|
||||
// 添加前,审计字段是空的
|
||||
Console.WriteLine("添加前:");
|
||||
Console.WriteLine($" CreatedAt: {product.CreatedAt}");
|
||||
Console.WriteLine($" CreatedBy: {product.CreatedBy ?? "(null)"}");
|
||||
|
||||
await repo.AddAsync(product);
|
||||
await db.SaveChangesAsync(); // SaveChanges 时自动填充审计信息
|
||||
|
||||
var afterCreate = DateTime.UtcNow;
|
||||
|
||||
// 添加后,审计字段自动填充
|
||||
Console.WriteLine("\n添加后:");
|
||||
Console.WriteLine($" ✓ CreatedAt: {product.CreatedAt:yyyy-MM-dd HH:mm:ss}");
|
||||
Console.WriteLine($" ✓ CreatedBy: {product.CreatedBy}");
|
||||
Console.WriteLine($" ✓ UpdatedAt: {product.UpdatedAt?.ToString("yyyy-MM-dd HH:mm:ss") ?? "(null)"}");
|
||||
Console.WriteLine($" ✓ UpdatedBy: {product.UpdatedBy ?? "(null)"}");
|
||||
|
||||
// 验证
|
||||
Assert.IsTrue(product.CreatedAt >= beforeCreate && product.CreatedAt <= afterCreate);
|
||||
Assert.AreEqual("zhang.san", product.CreatedBy);
|
||||
Assert.IsNull(product.UpdatedAt); // 创建时 UpdatedAt 为 null
|
||||
Assert.IsNull(product.UpdatedBy);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 演示: 审计功能 - 更新时自动记录
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public async Task Demo_AuditOnUpdate()
|
||||
{
|
||||
var builder = new DataContextBuilder<TestDbContext>();
|
||||
builder.UseInMemoryDatabase($"AuditUpdateDemo_{Guid.NewGuid()}")
|
||||
.UseAudit(true)
|
||||
.UseCurrentUser("creator");
|
||||
|
||||
using var db = builder.Build();
|
||||
var repo = db.Repository<Product>();
|
||||
|
||||
// 1. 创建产品 (创建人: creator)
|
||||
var product = new Product
|
||||
{
|
||||
Name = "原始产品",
|
||||
Price = 100m,
|
||||
Stock = 10
|
||||
};
|
||||
await repo.AddAsync(product);
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
Console.WriteLine("创建后的审计信息:");
|
||||
Console.WriteLine($" CreatedBy: {product.CreatedBy}");
|
||||
Console.WriteLine($" CreatedAt: {product.CreatedAt:yyyy-MM-dd HH:mm:ss}");
|
||||
|
||||
var createdAt = product.CreatedAt;
|
||||
var createdBy = product.CreatedBy;
|
||||
|
||||
// 等待一小段时间
|
||||
await Task.Delay(100);
|
||||
|
||||
// 2. 更改当前用户并更新产品
|
||||
// 注意:如果需要切换用户,请创建新的 DataContext
|
||||
// (db as Sharp.Data.Context.DataContext)?.SetCurrentUser("editor");
|
||||
|
||||
product.Name = "更新后的产品";
|
||||
product.Price = 200m;
|
||||
repo.Update(product);
|
||||
await db.SaveChangesAsync(); // SaveChanges 时自动填充 UpdatedAt 和 UpdatedBy
|
||||
|
||||
Console.WriteLine("\n更新后的审计信息:");
|
||||
Console.WriteLine($" CreatedBy: {product.CreatedBy} (保持不变)");
|
||||
Console.WriteLine($" CreatedAt: {product.CreatedAt:yyyy-MM-dd HH:mm:ss} (保持不变)");
|
||||
Console.WriteLine($" ✓ UpdatedBy: {product.UpdatedBy}");
|
||||
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.IsNotNull(product.UpdatedAt);
|
||||
Assert.IsTrue(product.UpdatedAt > product.CreatedAt); // 更新时间晚于创建时间
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 演示: 多次更新的审计记录
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public async Task Demo_MultipleUpdatesAudit()
|
||||
{
|
||||
var builder = new DataContextBuilder<TestDbContext>();
|
||||
builder.UseInMemoryDatabase($"MultiUpdateDemo_{Guid.NewGuid()}")
|
||||
.UseAudit(true)
|
||||
.UseCurrentUser("user1");
|
||||
|
||||
using var db = builder.Build();
|
||||
var repo = db.Repository<Product>();
|
||||
|
||||
// 创建产品
|
||||
var product = new Product { Name = "产品", Price = 100m, Stock = 10 };
|
||||
await repo.AddAsync(product);
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
Console.WriteLine($"创建: {product.CreatedBy} 于 {product.CreatedAt:HH:mm:ss}");
|
||||
|
||||
// 第一次更新
|
||||
await Task.Delay(50);
|
||||
// 注意:如果需要切换用户,请创建新的 DataContext
|
||||
// (db as Sharp.Data.Context.DataContext)?.SetCurrentUser("user2");
|
||||
product.Price = 150m;
|
||||
repo.Update(product);
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
var firstUpdateTime = product.UpdatedAt!.Value;
|
||||
Console.WriteLine($"第1次更新: {product.UpdatedBy} 于 {product.UpdatedAt:HH:mm:ss}");
|
||||
|
||||
// 第二次更新
|
||||
await Task.Delay(50);
|
||||
// 注意:如果需要切换用户,请创建新的 DataContext
|
||||
// (db as Sharp.Data.Context.DataContext)?.SetCurrentUser("user3");
|
||||
product.Price = 200m;
|
||||
repo.Update(product);
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
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); // 更新时间在变化
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 演示: 动态获取当前用户
|
||||
///
|
||||
/// 在真实应用中,用户信息通常来自认证系统
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public async Task Demo_DynamicUserProvider()
|
||||
{
|
||||
// 模拟当前登录用户(实际应用中可能来自 HttpContext、Session 等)
|
||||
var currentUser = "zhang.san";
|
||||
|
||||
var builder = new DataContextBuilder<TestDbContext>();
|
||||
builder.UseInMemoryDatabase($"DynamicUserDemo_{Guid.NewGuid()}")
|
||||
.UseAudit(true)
|
||||
.UseCurrentUserProvider(() =>
|
||||
{
|
||||
// 这里可以放置获取当前用户的逻辑
|
||||
// 例如: Thread.CurrentPrincipal?.Identity?.Name
|
||||
// HttpContext.Current?.User?.Identity?.Name
|
||||
// 某个全局的用户服务
|
||||
return currentUser;
|
||||
});
|
||||
|
||||
using var db = builder.Build();
|
||||
var repo = db.Repository<Product>();
|
||||
|
||||
// 用户 zhang.san 创建产品
|
||||
var product = new Product { Name = "产品A", Price = 100m, Stock = 10 };
|
||||
await repo.AddAsync(product);
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
Console.WriteLine($"✓ 创建人: {product.CreatedBy}");
|
||||
Assert.AreEqual("zhang.san", product.CreatedBy);
|
||||
|
||||
// 切换用户
|
||||
currentUser = "li.si";
|
||||
|
||||
// 用户 li.si 更新产品
|
||||
product.Price = 200m;
|
||||
repo.Update(product);
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
Console.WriteLine($"✓ 更新人: {product.UpdatedBy}");
|
||||
Assert.AreEqual("zhang.san", product.CreatedBy); // 创建人不变
|
||||
Assert.AreEqual("li.si", product.UpdatedBy); // 更新人改变
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 演示: 实现审计接口但不使用基类
|
||||
///
|
||||
/// Order 实体实现了 IAuditableEntity 接口,同样享受审计功能
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public async Task Demo_AuditWithInterface()
|
||||
{
|
||||
var builder = new DataContextBuilder<TestDbContext>();
|
||||
builder.UseInMemoryDatabase($"InterfaceAuditDemo_{Guid.NewGuid()}")
|
||||
.UseAudit(true)
|
||||
.UseCurrentUser("admin");
|
||||
|
||||
using var db = builder.Build();
|
||||
var repo = db.Repository<Order>();
|
||||
|
||||
// 创建订单
|
||||
var order = new Order
|
||||
{
|
||||
OrderNumber = "ORD-001",
|
||||
TotalAmount = 999.00m
|
||||
};
|
||||
await repo.AddAsync(order);
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
Console.WriteLine("✓ Order 实体(实现接口但不使用基类)同样享受审计功能");
|
||||
Console.WriteLine($" CreatedBy: {order.CreatedBy}");
|
||||
Console.WriteLine($" CreatedAt: {order.CreatedAt:yyyy-MM-dd HH:mm:ss}");
|
||||
|
||||
// 验证
|
||||
Assert.AreEqual("admin", order.CreatedBy);
|
||||
Assert.IsTrue(order.CreatedAt > DateTime.MinValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 演示: 不使用审计的实体不受影响
|
||||
///
|
||||
/// Category 不继承 AuditableEntity,也不实现审计接口
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public async Task Demo_NoAuditForNonAuditableEntity()
|
||||
{
|
||||
var builder = new DataContextBuilder<TestDbContext>();
|
||||
builder.UseInMemoryDatabase($"NoAuditDemo_{Guid.NewGuid()}")
|
||||
.UseAudit(true) // 即使启用了审计功能
|
||||
.UseCurrentUser("admin");
|
||||
|
||||
using var db = builder.Build();
|
||||
var repo = db.Repository<Category>();
|
||||
|
||||
// 创建分类
|
||||
var category = new Category { Name = "测试分类" };
|
||||
await repo.AddAsync(category);
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
Console.WriteLine("✓ Category 不实现审计接口,不受审计功能影响");
|
||||
Console.WriteLine($" 只有 Id 和业务字段: {category.Id}, {category.Name}");
|
||||
|
||||
// 验证:Category 没有审计字段
|
||||
Assert.IsNotNull(category.Id);
|
||||
Assert.AreEqual("测试分类", category.Name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 演示: 禁用审计功能
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public async Task Demo_DisableAudit()
|
||||
{
|
||||
var builder = new DataContextBuilder<TestDbContext>();
|
||||
builder.UseInMemoryDatabase($"DisableAuditDemo_{Guid.NewGuid()}")
|
||||
.UseAudit(false) // 禁用审计功能
|
||||
.UseCurrentUser("admin");
|
||||
|
||||
using var db = builder.Build();
|
||||
var repo = db.Repository<Product>();
|
||||
|
||||
// 创建产品
|
||||
var product = new Product { Name = "测试产品", Price = 100m, Stock = 10 };
|
||||
await repo.AddAsync(product);
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
Console.WriteLine("✓ 审计功能已禁用");
|
||||
Console.WriteLine($" CreatedBy: {product.CreatedBy ?? "(未设置)"}");
|
||||
Console.WriteLine($" CreatedAt: {product.CreatedAt}");
|
||||
|
||||
// 即使实体有审计字段,但功能禁用后,字段不会自动填充
|
||||
// 但 CreatedAt 可能有默认值(DateTime.MinValue 或当前时间,取决于实现)
|
||||
Console.WriteLine(" 注意:禁用审计后,即使实体有审计字段,也不会自动填充");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 演示: 审计功能的实际应用场景
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public async Task Demo_RealWorldAuditScenario()
|
||||
{
|
||||
var builder = new DataContextBuilder<TestDbContext>();
|
||||
builder.UseInMemoryDatabase($"RealWorldDemo_{Guid.NewGuid()}")
|
||||
.UseAudit(true)
|
||||
.UseCurrentUser("system");
|
||||
|
||||
using var db = builder.Build();
|
||||
var repo = db.Repository<Product>();
|
||||
|
||||
// 场景:产品生命周期跟踪
|
||||
|
||||
// 1. 系统初始化时创建产品
|
||||
var product = new Product
|
||||
{
|
||||
Name = "iPhone 15",
|
||||
Price = 7999m,
|
||||
Stock = 100
|
||||
};
|
||||
await repo.AddAsync(product);
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
Console.WriteLine("=== 产品生命周期审计 ===\n");
|
||||
Console.WriteLine($"1. 产品创建");
|
||||
Console.WriteLine($" 由 {product.CreatedBy} 于 {product.CreatedAt:yyyy-MM-dd HH:mm:ss} 创建");
|
||||
|
||||
// 2. 仓库管理员调整库存
|
||||
await Task.Delay(50);
|
||||
// 注意:如果需要切换用户,请创建新的 DataContext
|
||||
// (db as Sharp.Data.Context.DataContext)?.SetCurrentUser("warehouse.manager");
|
||||
product.Stock = 80;
|
||||
repo.Update(product);
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
Console.WriteLine($"\n2. 库存调整");
|
||||
Console.WriteLine($" 由 {product.UpdatedBy} 于 {product.UpdatedAt:yyyy-MM-dd HH:mm:ss} 更新");
|
||||
|
||||
// 3. 市场部调整价格
|
||||
await Task.Delay(50);
|
||||
// 注意:如果需要切换用户,请创建新的 DataContext
|
||||
// (db as Sharp.Data.Context.DataContext)?.SetCurrentUser("marketing.manager");
|
||||
product.Price = 6999m;
|
||||
repo.Update(product);
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
Console.WriteLine($"\n3. 价格调整");
|
||||
Console.WriteLine($" 由 {product.UpdatedBy} 于 {product.UpdatedAt:yyyy-MM-dd HH:mm:ss} 更新");
|
||||
|
||||
Console.WriteLine($"\n✓ 通过审计信息,可以追踪产品的完整变更历史");
|
||||
Console.WriteLine($" - 谁创建的:{product.CreatedBy}");
|
||||
Console.WriteLine($" - 何时创建:{product.CreatedAt:yyyy-MM-dd HH:mm:ss}");
|
||||
Console.WriteLine($" - 谁最后修改:{product.UpdatedBy}");
|
||||
Console.WriteLine($" - 何时修改:{product.UpdatedAt:yyyy-MM-dd HH:mm:ss}");
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user