Initial project import
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
using MiaoJiZhang.Domain.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
namespace MiaoJiZhang.Infrastructure.Persistence;
|
||||
|
||||
public class AppDbContext(DbContextOptions<AppDbContext> options) : DbContext(options)
|
||||
{
|
||||
public DbSet<User> Users => Set<User>();
|
||||
public DbSet<UserFeaturePermission> UserFeaturePermissions => Set<UserFeaturePermission>();
|
||||
public DbSet<AiCompanionSetting> AiCompanionSettings => Set<AiCompanionSetting>();
|
||||
public DbSet<Ledger> Ledgers => Set<Ledger>();
|
||||
public DbSet<Category> Categories => Set<Category>();
|
||||
public DbSet<Transaction> Transactions => Set<Transaction>();
|
||||
public DbSet<Budget> Budgets => Set<Budget>();
|
||||
public DbSet<ChatMessage> ChatMessages => Set<ChatMessage>();
|
||||
public DbSet<AppConfig> AppConfigs => Set<AppConfig>();
|
||||
public DbSet<AiPersona> AiPersonas => Set<AiPersona>();
|
||||
public DbSet<AiAvatar> AiAvatars => Set<AiAvatar>();
|
||||
public DbSet<Sticker> Stickers => Set<Sticker>();
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder b)
|
||||
{
|
||||
b.Entity<User>(e =>
|
||||
{
|
||||
e.HasIndex(x => x.Username).IsUnique();
|
||||
e.Property(x => x.Username).HasMaxLength(32);
|
||||
e.Property(x => x.Nickname).HasMaxLength(32);
|
||||
// 预留字段索引(唯一但允许 null)
|
||||
e.HasIndex(x => x.Email).IsUnique();
|
||||
e.HasIndex(x => x.Phone).IsUnique();
|
||||
e.HasIndex(x => x.WeChatOpenId).IsUnique();
|
||||
e.HasIndex(x => x.AccountClosureScheduledAt);
|
||||
e.HasOne(x => x.AiCompanion).WithOne(x => x.User)
|
||||
.HasForeignKey<AiCompanionSetting>(x => x.UserId);
|
||||
});
|
||||
|
||||
b.Entity<UserFeaturePermission>(e =>
|
||||
{
|
||||
e.Property(x => x.PermissionKey).HasMaxLength(32);
|
||||
e.HasIndex(x => new { x.UserId, x.PermissionKey }).IsUnique();
|
||||
e.HasOne(x => x.User).WithMany(x => x.FeaturePermissions)
|
||||
.HasForeignKey(x => x.UserId).OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
b.Entity<Transaction>(e =>
|
||||
{
|
||||
e.Property(x => x.Amount).HasPrecision(12, 2);
|
||||
e.HasIndex(x => new { x.LedgerId, x.OccurredAt });
|
||||
e.HasIndex(x => new { x.UserId, x.IsDeleted });
|
||||
e.Property(x => x.ClientRequestId).HasMaxLength(64);
|
||||
e.HasIndex(x => new { x.UserId, x.ClientRequestId }).IsUnique();
|
||||
e.HasQueryFilter(x => !x.IsDeleted); // 软删除全局过滤
|
||||
});
|
||||
|
||||
b.Entity<Category>(e => e.Property(x => x.ColorKey).HasMaxLength(32));
|
||||
|
||||
b.Entity<Budget>(e =>
|
||||
{
|
||||
e.Property(x => x.Amount).HasPrecision(12, 2);
|
||||
e.HasIndex(x => new { x.LedgerId, x.Period, x.CategoryId }).IsUnique();
|
||||
});
|
||||
|
||||
b.Entity<ChatMessage>(e => e.HasIndex(x => new { x.UserId, x.CreatedAt }));
|
||||
b.Entity<AppConfig>(e => e.HasIndex(x => x.Key).IsUnique());
|
||||
b.Entity<AiPersona>(e => e.HasIndex(x => x.Key).IsUnique());
|
||||
b.Entity<AiAvatar>(e => e.HasIndex(x => x.Key).IsUnique());
|
||||
b.Entity<Sticker>(e => e.HasIndex(x => x.Key).IsUnique());
|
||||
|
||||
// MySQL DATETIME has no timezone metadata. Preserve stored UTC wall-clock
|
||||
// values and restore DateTimeKind.Utc whenever EF materializes them.
|
||||
var utcDateTimeConverter = new ValueConverter<DateTime, DateTime>(
|
||||
value => value.Kind == DateTimeKind.Local
|
||||
? value.ToUniversalTime()
|
||||
: DateTime.SpecifyKind(value, DateTimeKind.Utc),
|
||||
value => DateTime.SpecifyKind(value, DateTimeKind.Utc));
|
||||
var nullableUtcDateTimeConverter = new ValueConverter<DateTime?, DateTime?>(
|
||||
value => value.HasValue
|
||||
? value.Value.Kind == DateTimeKind.Local
|
||||
? value.Value.ToUniversalTime()
|
||||
: DateTime.SpecifyKind(value.Value, DateTimeKind.Utc)
|
||||
: value,
|
||||
value => value.HasValue
|
||||
? DateTime.SpecifyKind(value.Value, DateTimeKind.Utc)
|
||||
: value);
|
||||
|
||||
foreach (var property in b.Model.GetEntityTypes().SelectMany(entity => entity.GetProperties()))
|
||||
{
|
||||
if (property.ClrType == typeof(DateTime))
|
||||
{
|
||||
property.SetValueConverter(utcDateTimeConverter);
|
||||
}
|
||||
else if (property.ClrType == typeof(DateTime?))
|
||||
{
|
||||
property.SetValueConverter(nullableUtcDateTimeConverter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user