diff --git a/.idea/.idea.Bunny.WebApi/.idea/dataSources.xml b/.idea/.idea.Bunny.WebApi/.idea/dataSources.xml
index a485d43..9b7261b 100644
--- a/.idea/.idea.Bunny.WebApi/.idea/dataSources.xml
+++ b/.idea/.idea.Bunny.WebApi/.idea/dataSources.xml
@@ -1,15 +1,23 @@
-
+
sqlite.xerial
true
org.sqlite.JDBC
- jdbc:sqlite:D:\MyFolder\Bunny\Bunny-cli\CSharp\CSharp-Single-EFCore\Bunny.WebApi\bunny.db
+ jdbc:sqlite:D:\Project\web\Bunny-Cli\template\CSharp\CSharp-Single-EFCore\Bunny.WebApi\Database\bunny.db
$ProjectFileDir$
+
+
+ file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/xerial/sqlite-jdbc/3.45.1.0/sqlite-jdbc-3.45.1.0.jar
+
+
+ file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar
+
+
\ No newline at end of file
diff --git a/Bunny.Common/AppSettings.cs b/Bunny.Common/AppSettings.cs
index ccacc50..6511662 100644
--- a/Bunny.Common/AppSettings.cs
+++ b/Bunny.Common/AppSettings.cs
@@ -57,11 +57,10 @@ public class AppSettings
}
- public static T GetAppConfig(string key, T? defaultValue = default)
+ public static T? GetAppConfig(string key, T? defaultValue = default)
{
- var setting = (T)Convert.ChangeType(Configuration[key], typeof(T));
- var value = setting;
- return value;
+ return (T)Convert.ChangeType(Configuration[key], typeof(T))!;
+ ;
}
///
@@ -71,7 +70,7 @@ public class AppSettings
///
public static string GetConfig(string key)
{
- return Configuration[key];
+ return Configuration[key]!;
}
///
@@ -82,6 +81,6 @@ public class AppSettings
/// 节点类型实例
public static T Get(string key)
{
- return Configuration.GetSection(key).Get();
+ return Configuration.GetSection(key).Get()!;
}
}
\ No newline at end of file
diff --git a/Bunny.Common/Bunny.Common.csproj b/Bunny.Common/Bunny.Common.csproj
index 67a2885..40c23a0 100644
--- a/Bunny.Common/Bunny.Common.csproj
+++ b/Bunny.Common/Bunny.Common.csproj
@@ -10,14 +10,14 @@
-
- all
+
runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
-
-
- all
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
diff --git a/Bunny.Common/Connect/EFCoreContext.cs b/Bunny.Common/Connect/EFCoreContext.cs
deleted file mode 100644
index 645970b..0000000
--- a/Bunny.Common/Connect/EFCoreContext.cs
+++ /dev/null
@@ -1,104 +0,0 @@
-using Bunny.Common.Context;
-using Bunny.Dao.Entity.Base;
-using Bunny.Dao.Entity.System;
-using Microsoft.EntityFrameworkCore;
-
-namespace Bunny.Common.Connect;
-
-public class EfCoreContext : DbContext
-{
- public EfCoreContext()
- {
- // DbPath = @"D:\MyFolder\Bunny\Bunny-cli\Template\CSharp\CSharp-Single-EFCore\Bunny.WebApi\Database\bunny.db";
- var dataBaseConnection = AppSettings.GetAppConfig("DataBase:DataBaseConnection");
- DbPath = dataBaseConnection;
- }
-
- public string DbPath { get; }
-
- public DbSet Blogs { get; set; }
- public DbSet Posts { get; set; }
- public DbSet Products { get; set; }
- public DbSet Users { get; set; }
-
- protected override void OnConfiguring(DbContextOptionsBuilder options)
- {
- options.UseSqlite($"Data Source={DbPath}");
- }
-
- protected override void OnModelCreating(ModelBuilder modelBuilder)
- {
- // 添加过滤器
- modelBuilder.Entity()
- .HasQueryFilter(e => !e.IsDeleted);
-
- // 默认值为false,表示未删除
- modelBuilder.Entity()
- .Property(e => e.IsDeleted)
- .HasDefaultValue(false);
-
- base.OnModelCreating(modelBuilder);
- }
-
- public override int SaveChanges()
- {
- SetSystemField();
- return base.SaveChanges();
- }
-
- public override int SaveChanges(bool acceptAllChangesOnSuccess)
- {
- SetSystemField();
- return base.SaveChanges(acceptAllChangesOnSuccess);
- }
-
- public override Task SaveChangesAsync(CancellationToken cancellationToken = new())
- {
- SetSystemField();
- return base.SaveChangesAsync(cancellationToken);
- }
-
- public override Task SaveChangesAsync(bool acceptAllChangesOnSuccess,
- CancellationToken cancellationToken = new())
- {
- SetSystemField();
- return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
- }
-
- ///
- /// 系统字段赋值
- ///
- private void SetSystemField()
- {
- foreach (var item in ChangeTracker.Entries())
- if (item.Entity is BaseEntity entity)
- switch (item.State)
- {
- //添加操作
- case EntityState.Added:
- {
- if (entity.Id == string.Empty) entity.Id = Guid.NewGuid().ToString();
- entity.CreateTime = DateTime.Now;
- entity.UpdateTime = DateTime.Now;
- entity.CreateUserId = BaseContext.GetUserId()!.Value;
- entity.UpdateUserId = BaseContext.GetUserId()!.Value;
- break;
- }
- //修改操作
- case EntityState.Modified:
- entity.UpdateTime = DateTime.Now;
- entity.UpdateUserId = BaseContext.GetUserId()!.Value;
- break;
- case EntityState.Detached:
- break;
- case EntityState.Unchanged:
- break;
- case EntityState.Deleted:
- entity.UpdateTime = DateTime.Now;
- entity.UpdateUserId = BaseContext.GetUserId()!.Value;
- break;
- default:
- throw new ArgumentOutOfRangeException();
- }
- }
-}
\ No newline at end of file
diff --git a/Bunny.Common/Context/BaseContext.cs b/Bunny.Common/Context/BaseContext.cs
index 297d59e..2eab517 100644
--- a/Bunny.Common/Context/BaseContext.cs
+++ b/Bunny.Common/Context/BaseContext.cs
@@ -3,33 +3,33 @@
public class BaseContext
{
// 使用Lazy初始化确保线程安全
- public static readonly ThreadLocal UserId = new();
- public static readonly ThreadLocal Token = new();
+ public static readonly ThreadLocal? UserId = null;
+ public static readonly ThreadLocal? Token = null;
// 用户id相关
public static long? GetUserId()
{
- return UserId.Value;
+ return UserId?.Value;
}
public static void SetUserId(long? userId)
{
- UserId.Value = userId;
+ UserId!.Value = userId;
}
public static string? GetToken()
{
- return Token.Value;
+ return Token?.Value;
}
public static void SetToken(string token)
{
- Token.Value = token;
+ Token!.Value = token;
}
public static void RemoveUser()
{
- Token.Value = null;
- UserId.Value = null;
+ if (Token != null) Token.Value = null;
+ if (UserId != null) UserId.Value = null;
}
}
\ No newline at end of file
diff --git a/Bunny.Common/Context/EFCoreContext.cs b/Bunny.Common/Context/EFCoreContext.cs
new file mode 100644
index 0000000..a46aefb
--- /dev/null
+++ b/Bunny.Common/Context/EFCoreContext.cs
@@ -0,0 +1,123 @@
+using Bunny.Common.Interceptor;
+using Bunny.Dao.Entity.Base;
+using Bunny.Dao.Entity.System;
+using Microsoft.EntityFrameworkCore;
+
+namespace Bunny.Common.Context;
+
+///
+/// EfCore 连接内容
+/// dotnet tool install --global dotnet-ef
+/// dotnet add package Microsoft.EntityFrameworkCore.Design
+/// dotnet ef migrations add InitialCreate
+/// dotnet ef database update
+///
+public class EfCoreContext : DbContext
+{
+ public EfCoreContext()
+ {
+ // var dataBaseConnection = AppSettings.GetAppConfig("DataBase:DataBaseConnection");
+ const string dataBaseConnection =
+ "192.168.3.98;Initial Catalog=BunnyDemo;TrustServerCertificate=True;Persist Security Info=True;User ID=sa;Password=abc1234.";
+ DbPath = $"Data Source={dataBaseConnection}";
+ }
+
+ // 连接路径
+ private string DbPath { get; }
+ public DbSet Blogs { get; set; }
+ public DbSet Posts { get; set; }
+ public DbSet Products { get; set; }
+ public DbSet Users { get; set; }
+
+ ///
+ /// 配置数据库上下文选项,指定数据库连接字符串
+ ///
+ protected override void OnConfiguring(DbContextOptionsBuilder options)
+ {
+ options.UseSqlServer(DbPath).AddInterceptors(new TransactionInterceptor());
+ }
+
+ ///
+ /// 在创建模型时,为所有继承自BaseEntity的实体类型添加软删除查询过滤器
+ ///
+ protected override void OnModelCreating(ModelBuilder modelBuilder)
+ {
+ foreach (var entityType in modelBuilder.Model.GetEntityTypes())
+ if (typeof(BaseEntity).IsAssignableFrom(entityType.ClrType))
+ entityType.AddSoftDeleteQueryFilter();
+
+ base.OnModelCreating(modelBuilder);
+ }
+
+ ///
+ /// 重写SaveChanges方法,在保存更改之前设置系统字段
+ ///
+ public override int SaveChanges()
+ {
+ SetSystemField();
+ return base.SaveChanges();
+ }
+
+ ///
+ /// 重写SaveChanges方法,在保存更改之前设置系统字段
+ ///
+ public override int SaveChanges(bool acceptAllChangesOnSuccess)
+ {
+ SetSystemField();
+ return base.SaveChanges(acceptAllChangesOnSuccess);
+ }
+
+ ///
+ /// 异步保存更改,设置系统字段
+ ///
+ public override Task SaveChangesAsync(CancellationToken cancellationToken = new())
+ {
+ SetSystemField();
+ return base.SaveChangesAsync(cancellationToken);
+ }
+
+ ///
+ /// 异步保存更改,设置系统字段
+ ///
+ public override Task SaveChangesAsync(bool acceptAllChangesOnSuccess,
+ CancellationToken cancellationToken = new())
+ {
+ SetSystemField();
+ return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
+ }
+
+ ///
+ /// 系统字段赋值
+ ///
+ private void SetSystemField()
+ {
+ foreach (var item in ChangeTracker.Entries())
+ if (item.Entity is BaseEntity entity)
+ {
+ var userId = BaseContext.GetUserId();
+ switch (item.State)
+ {
+ // 添加操作
+ case EntityState.Added:
+ {
+ if (entity.Id == Guid.Empty) entity.Id = Guid.NewGuid();
+ entity.CreateTime = DateTime.Now;
+ entity.UpdateTime = DateTime.Now;
+ // 判断用户Id是否为空
+ if (userId != null)
+ {
+ entity.CreateUserId = userId!.Value;
+ entity.UpdateUserId = userId!.Value;
+ }
+
+ break;
+ }
+ // 修改操作
+ case EntityState.Modified:
+ entity.UpdateTime = DateTime.Now;
+ if (userId != null) entity.UpdateUserId = userId!.Value;
+ break;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Bunny.Common/Configuration/JsonDateTimeConverter.cs b/Bunny.Common/Context/JsonDateTimeConverter.cs
similarity index 97%
rename from Bunny.Common/Configuration/JsonDateTimeConverter.cs
rename to Bunny.Common/Context/JsonDateTimeConverter.cs
index 05dca84..8a7db46 100644
--- a/Bunny.Common/Configuration/JsonDateTimeConverter.cs
+++ b/Bunny.Common/Context/JsonDateTimeConverter.cs
@@ -2,7 +2,7 @@
using System.Text.Json.Serialization;
using Bunny.Dao.Model.Constant;
-namespace Bunny.Common.Configuration;
+namespace Bunny.Common.Context;
///
/// 自定义Json转换器,用于将DateTime类型转换为JSON格式
diff --git a/Bunny.Common/Connect/MinioContext.cs b/Bunny.Common/Context/MinioContext.cs
similarity index 95%
rename from Bunny.Common/Connect/MinioContext.cs
rename to Bunny.Common/Context/MinioContext.cs
index 19044bb..ab6b13b 100644
--- a/Bunny.Common/Connect/MinioContext.cs
+++ b/Bunny.Common/Context/MinioContext.cs
@@ -1,7 +1,7 @@
using Microsoft.AspNetCore.Builder;
using Minio;
-namespace Bunny.Common.Connect;
+namespace Bunny.Common.Context;
public static class MinioContext
{
diff --git a/Bunny.Common/Connect/RedisContext.cs b/Bunny.Common/Context/RedisContext.cs
similarity index 94%
rename from Bunny.Common/Connect/RedisContext.cs
rename to Bunny.Common/Context/RedisContext.cs
index c8bd9d3..bf6d9e5 100644
--- a/Bunny.Common/Connect/RedisContext.cs
+++ b/Bunny.Common/Context/RedisContext.cs
@@ -1,11 +1,11 @@
using Microsoft.AspNetCore.Builder;
using StackExchange.Redis;
-namespace Bunny.Common.Connect;
+namespace Bunny.Common.Context;
public static class RedisContext
{
- public static IDatabase RedisDatabase;
+ public static IDatabase? RedisDatabase;
private static readonly EndPointCollection EndPointCollection = new();
public static void AddRedisContext(this WebApplicationBuilder builder)
diff --git a/Bunny.Common/Context/SoftDeleteQueryExtension.cs b/Bunny.Common/Context/SoftDeleteQueryExtension.cs
new file mode 100644
index 0000000..5a8863a
--- /dev/null
+++ b/Bunny.Common/Context/SoftDeleteQueryExtension.cs
@@ -0,0 +1,36 @@
+using System.Linq.Expressions;
+using System.Reflection;
+using Bunny.Dao.Entity.Base;
+using Microsoft.EntityFrameworkCore.Metadata;
+
+namespace Bunny.Common.Context;
+
+///
+/// 软删除过滤器
+///
+public static class SoftDeleteQueryExtension
+{
+ ///
+ /// 软删除过滤器
+ ///
+ ///
+ public static void AddSoftDeleteQueryFilter(this IMutableEntityType entityData)
+ {
+ var methodToCall = typeof(SoftDeleteQueryExtension)
+ .GetMethod(nameof(GetSoftDeleteFilter), BindingFlags.NonPublic | BindingFlags.Static)
+ ?.MakeGenericMethod(entityData.ClrType);
+ var filter = methodToCall?.Invoke(null, []);
+ entityData.SetQueryFilter((LambdaExpression)filter!);
+ }
+
+ ///
+ /// 软删除
+ ///
+ ///
+ ///
+ private static LambdaExpression GetSoftDeleteFilter() where TEntity : BaseEntity
+ {
+ Expression> filter = x => !x.IsDeleted;
+ return filter;
+ }
+}
\ No newline at end of file
diff --git a/Bunny.Common/Filter/ValidateModelStateAttribute.cs b/Bunny.Common/Filter/ValidateModelStateAttribute.cs
index dec9952..a5fba3d 100644
--- a/Bunny.Common/Filter/ValidateModelStateAttribute.cs
+++ b/Bunny.Common/Filter/ValidateModelStateAttribute.cs
@@ -2,6 +2,7 @@
using Bunny.Dao.Model.Result;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
+using Microsoft.AspNetCore.Mvc.ModelBinding;
namespace Bunny.Common.Filter;
@@ -14,9 +15,10 @@ public class ValidateModelStateAttribute : ActionFilterAttribute
{
if (actionContext.ModelState.IsValid) return;
- // 异常返回结果包装 也可以自定自定义返回类型
+ // 表单验证失败
var errorMessage = actionContext.ModelState.Values.First().Errors.First().ErrorMessage;
- var result = Result.Error(HttpStatusCode.BadRequest, errorMessage);
+ var result =
+ Result.Error(HttpStatusCode.BadRequest, actionContext.ModelState, errorMessage);
// 重新复写返回结果
actionContext.Result = new ObjectResult(result);
diff --git a/Bunny.Common/Interceptor/TransactionInterceptor.cs b/Bunny.Common/Interceptor/TransactionInterceptor.cs
new file mode 100644
index 0000000..8bfbdb6
--- /dev/null
+++ b/Bunny.Common/Interceptor/TransactionInterceptor.cs
@@ -0,0 +1,30 @@
+using Bunny.Common.Exception;
+using Bunny.Dao.Model.Constant;
+using Microsoft.EntityFrameworkCore.Diagnostics;
+
+namespace Bunny.Common.Interceptor;
+
+public class TransactionInterceptor : SaveChangesInterceptor
+{
+ public override InterceptionResult SavingChanges(DbContextEventData eventData, InterceptionResult result)
+ {
+ if (eventData.Context!.Database.CurrentTransaction != null) return result;
+ using var transaction = eventData.Context.Database.BeginTransaction();
+ try
+ {
+ // 调用基类方法继续保存更改
+ result = base.SavingChanges(eventData, result);
+
+ // 如果保存更改成功,则提交事务
+ transaction.Commit();
+ }
+ catch (System.Exception)
+ {
+ // 如果保存更改失败,则回滚事务
+ transaction.Rollback();
+ throw new BunnyException(ExceptionConstant.DataBaseError);
+ }
+
+ return result;
+ }
+}
\ No newline at end of file
diff --git a/Bunny.Common/Migrations/20240809011221_InitialCreate.Designer.cs b/Bunny.Common/Migrations/20240809011221_InitialCreate.Designer.cs
deleted file mode 100644
index 1eba6a2..0000000
--- a/Bunny.Common/Migrations/20240809011221_InitialCreate.Designer.cs
+++ /dev/null
@@ -1,173 +0,0 @@
-//
-using System;
-using Bunny.Common.Connect;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Migrations;
-using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-
-#nullable disable
-
-namespace Bunny.Common.Migrations
-{
- [DbContext(typeof(EfCoreContext))]
- [Migration("20240809011221_InitialCreate")]
- partial class InitialCreate
- {
- ///
- protected override void BuildTargetModel(ModelBuilder modelBuilder)
- {
-#pragma warning disable 612, 618
- modelBuilder.HasAnnotation("ProductVersion", "8.0.7");
-
- modelBuilder.Entity("Bunny.Dao.Models.System.Blog", b =>
- {
- b.Property("Id")
- .HasColumnType("TEXT");
-
- b.Property("CreateTime")
- .HasColumnType("TEXT");
-
- b.Property("CreateUserId")
- .HasColumnType("INTEGER");
-
- b.Property("UpdateTime")
- .HasColumnType("TEXT");
-
- b.Property("UpdateUserId")
- .HasColumnType("INTEGER");
-
- b.Property("Url")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.HasKey("Id");
-
- b.ToTable("Blogs");
- });
-
- modelBuilder.Entity("Bunny.Dao.Models.System.Post", b =>
- {
- b.Property("Id")
- .HasColumnType("TEXT");
-
- b.Property("BlogId")
- .HasColumnType("INTEGER");
-
- b.Property("BlogId1")
- .HasColumnType("TEXT");
-
- b.Property("Content")
- .HasColumnType("TEXT");
-
- b.Property("CreateTime")
- .HasColumnType("TEXT");
-
- b.Property("CreateUserId")
- .HasColumnType("INTEGER");
-
- b.Property("PostId")
- .HasColumnType("INTEGER");
-
- b.Property("Title")
- .HasColumnType("TEXT");
-
- b.Property("UpdateTime")
- .HasColumnType("TEXT");
-
- b.Property("UpdateUserId")
- .HasColumnType("INTEGER");
-
- b.HasKey("Id");
-
- b.HasIndex("BlogId1");
-
- b.ToTable("Posts");
- });
-
- modelBuilder.Entity("Bunny.Dao.Models.System.Product", b =>
- {
- b.Property("Id")
- .HasColumnType("TEXT");
-
- b.Property("CreateTime")
- .HasColumnType("TEXT");
-
- b.Property("CreateUserId")
- .HasColumnType("INTEGER");
-
- b.Property("CustomerId")
- .HasColumnType("TEXT");
-
- b.Property("CustomerName")
- .HasColumnType("TEXT");
-
- b.Property("PackageType")
- .HasColumnType("TEXT");
-
- b.Property("UpdateTime")
- .HasColumnType("TEXT");
-
- b.Property("UpdateUserId")
- .HasColumnType("INTEGER");
-
- b.HasKey("Id");
-
- b.ToTable("Products");
- });
-
- modelBuilder.Entity("Bunny.Dao.Models.System.User", b =>
- {
- b.Property("Id")
- .HasColumnType("TEXT");
-
- b.Property("CompanyCode")
- .HasColumnType("TEXT");
-
- b.Property("CreateTime")
- .HasColumnType("TEXT");
-
- b.Property("CreateUserId")
- .HasColumnType("INTEGER");
-
- b.Property("DeptCode")
- .HasColumnType("TEXT");
-
- b.Property("Email")
- .HasColumnType("TEXT");
-
- b.Property("Password")
- .HasColumnType("TEXT");
-
- b.Property("Phone")
- .HasColumnType("TEXT");
-
- b.Property("QrCode")
- .HasColumnType("TEXT");
-
- b.Property("UpdateTime")
- .HasColumnType("TEXT");
-
- b.Property("UpdateUserId")
- .HasColumnType("INTEGER");
-
- b.Property("UserName")
- .HasColumnType("TEXT");
-
- b.HasKey("Id");
-
- b.ToTable("Users");
- });
-
- modelBuilder.Entity("Bunny.Dao.Models.System.Post", b =>
- {
- b.HasOne("Bunny.Dao.Models.System.Blog", "Blog")
- .WithMany()
- .HasForeignKey("BlogId1");
-
- b.Navigation("Blog");
- });
-#pragma warning restore 612, 618
- }
- }
-}
diff --git a/Bunny.Common/Migrations/20240809011221_InitialCreate.cs b/Bunny.Common/Migrations/20240809011221_InitialCreate.cs
deleted file mode 100644
index 04f8424..0000000
--- a/Bunny.Common/Migrations/20240809011221_InitialCreate.cs
+++ /dev/null
@@ -1,117 +0,0 @@
-using System;
-using Microsoft.EntityFrameworkCore.Migrations;
-
-#nullable disable
-
-namespace Bunny.Common.Migrations
-{
- ///
- public partial class InitialCreate : Migration
- {
- ///
- protected override void Up(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.CreateTable(
- name: "Blogs",
- columns: table => new
- {
- Id = table.Column(type: "TEXT", nullable: false),
- Url = table.Column(type: "TEXT", nullable: false),
- CreateTime = table.Column(type: "TEXT", nullable: false),
- UpdateTime = table.Column(type: "TEXT", nullable: false),
- CreateUserId = table.Column(type: "INTEGER", nullable: false),
- UpdateUserId = table.Column(type: "INTEGER", nullable: false)
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_Blogs", x => x.Id);
- });
-
- migrationBuilder.CreateTable(
- name: "Products",
- columns: table => new
- {
- Id = table.Column(type: "TEXT", nullable: false),
- CustomerId = table.Column(type: "TEXT", nullable: true),
- CustomerName = table.Column(type: "TEXT", nullable: true),
- PackageType = table.Column(type: "TEXT", nullable: true),
- CreateTime = table.Column(type: "TEXT", nullable: false),
- UpdateTime = table.Column(type: "TEXT", nullable: false),
- CreateUserId = table.Column(type: "INTEGER", nullable: false),
- UpdateUserId = table.Column(type: "INTEGER", nullable: false)
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_Products", x => x.Id);
- });
-
- migrationBuilder.CreateTable(
- name: "Users",
- columns: table => new
- {
- Id = table.Column(type: "TEXT", nullable: false),
- UserName = table.Column(type: "TEXT", nullable: true),
- Password = table.Column(type: "TEXT", nullable: true),
- Email = table.Column(type: "TEXT", nullable: true),
- Phone = table.Column(type: "TEXT", nullable: true),
- QrCode = table.Column(type: "TEXT", nullable: true),
- CompanyCode = table.Column(type: "TEXT", nullable: true),
- DeptCode = table.Column(type: "TEXT", nullable: true),
- CreateTime = table.Column(type: "TEXT", nullable: false),
- UpdateTime = table.Column(type: "TEXT", nullable: false),
- CreateUserId = table.Column(type: "INTEGER", nullable: false),
- UpdateUserId = table.Column(type: "INTEGER", nullable: false)
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_Users", x => x.Id);
- });
-
- migrationBuilder.CreateTable(
- name: "Posts",
- columns: table => new
- {
- Id = table.Column(type: "TEXT", nullable: false),
- PostId = table.Column(type: "INTEGER", nullable: false),
- Title = table.Column(type: "TEXT", nullable: true),
- Content = table.Column(type: "TEXT", nullable: true),
- BlogId = table.Column(type: "INTEGER", nullable: false),
- BlogId1 = table.Column(type: "TEXT", nullable: true),
- CreateTime = table.Column(type: "TEXT", nullable: false),
- UpdateTime = table.Column(type: "TEXT", nullable: false),
- CreateUserId = table.Column(type: "INTEGER", nullable: false),
- UpdateUserId = table.Column(type: "INTEGER", nullable: false)
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_Posts", x => x.Id);
- table.ForeignKey(
- name: "FK_Posts_Blogs_BlogId1",
- column: x => x.BlogId1,
- principalTable: "Blogs",
- principalColumn: "Id");
- });
-
- migrationBuilder.CreateIndex(
- name: "IX_Posts_BlogId1",
- table: "Posts",
- column: "BlogId1");
- }
-
- ///
- protected override void Down(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.DropTable(
- name: "Posts");
-
- migrationBuilder.DropTable(
- name: "Products");
-
- migrationBuilder.DropTable(
- name: "Users");
-
- migrationBuilder.DropTable(
- name: "Blogs");
- }
- }
-}
diff --git a/Bunny.Common/Migrations/20240902054644_InitialCreate.Designer.cs b/Bunny.Common/Migrations/20240902054644_InitialCreate.Designer.cs
new file mode 100644
index 0000000..9e2b4af
--- /dev/null
+++ b/Bunny.Common/Migrations/20240902054644_InitialCreate.Designer.cs
@@ -0,0 +1,186 @@
+//
+using System;
+using Bunny.Common.Context;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+#nullable disable
+
+namespace Bunny.Common.Migrations
+{
+ [DbContext(typeof(EfCoreContext))]
+ [Migration("20240902054644_InitialCreate")]
+ partial class InitialCreate
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "8.0.8")
+ .HasAnnotation("Relational:MaxIdentifierLength", 128);
+
+ SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
+
+ modelBuilder.Entity("Bunny.Dao.Entity.System.Blog", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("nvarchar(450)");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("bigint");
+
+ b.Property("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property("UpdateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("UpdateUserId")
+ .HasColumnType("bigint");
+
+ b.Property("Url")
+ .IsRequired()
+ .HasColumnType("varchar(600)")
+ .HasColumnName("BlogUrl");
+
+ b.HasKey("Id");
+
+ b.ToTable("Blog");
+ });
+
+ modelBuilder.Entity("Bunny.Dao.Entity.System.Post", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("nvarchar(450)");
+
+ b.Property("BlogId")
+ .HasColumnType("nvarchar(450)");
+
+ b.Property("Content")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("bigint");
+
+ b.Property("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property("Title")
+ .HasMaxLength(600)
+ .HasColumnType("nvarchar(600)");
+
+ b.Property("UpdateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("UpdateUserId")
+ .HasColumnType("bigint");
+
+ b.HasKey("Id");
+
+ b.HasIndex("BlogId");
+
+ b.ToTable("Posts");
+ });
+
+ modelBuilder.Entity("Bunny.Dao.Entity.System.Product", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("nvarchar(450)");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("bigint");
+
+ b.Property("CustomerId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("CustomerName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property("PackageType")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("UpdateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("UpdateUserId")
+ .HasColumnType("bigint");
+
+ b.HasKey("Id");
+
+ b.ToTable("Products");
+ });
+
+ modelBuilder.Entity("Bunny.Dao.Entity.System.User", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("nvarchar(450)");
+
+ b.Property("CompanyCode")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("bigint");
+
+ b.Property("DeptCode")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("Email")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property("Password")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("Phone")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("QrCode")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("UpdateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("UpdateUserId")
+ .HasColumnType("bigint");
+
+ b.Property("UserName")
+ .HasColumnType("nvarchar(max)");
+
+ b.HasKey("Id");
+
+ b.ToTable("Users");
+ });
+
+ modelBuilder.Entity("Bunny.Dao.Entity.System.Post", b =>
+ {
+ b.HasOne("Bunny.Dao.Entity.System.Blog", "Blog")
+ .WithMany()
+ .HasForeignKey("BlogId");
+
+ b.Navigation("Blog");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/Bunny.Common/Migrations/20240902054644_InitialCreate.cs b/Bunny.Common/Migrations/20240902054644_InitialCreate.cs
new file mode 100644
index 0000000..a93b535
--- /dev/null
+++ b/Bunny.Common/Migrations/20240902054644_InitialCreate.cs
@@ -0,0 +1,119 @@
+using System;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace Bunny.Common.Migrations
+{
+ ///
+ public partial class InitialCreate : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.CreateTable(
+ name: "Blog",
+ columns: table => new
+ {
+ Id = table.Column(type: "nvarchar(450)", nullable: false),
+ BlogUrl = table.Column(type: "varchar(600)", nullable: false),
+ CreateTime = table.Column(type: "datetime2", nullable: false),
+ UpdateTime = table.Column(type: "datetime2", nullable: false),
+ CreateUserId = table.Column(type: "bigint", nullable: false),
+ UpdateUserId = table.Column(type: "bigint", nullable: false),
+ IsDeleted = table.Column(type: "bit", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Blog", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "Products",
+ columns: table => new
+ {
+ Id = table.Column(type: "nvarchar(450)", nullable: false),
+ CustomerId = table.Column(type: "nvarchar(max)", nullable: true),
+ CustomerName = table.Column(type: "nvarchar(max)", nullable: true),
+ PackageType = table.Column(type: "nvarchar(max)", nullable: true),
+ CreateTime = table.Column(type: "datetime2", nullable: false),
+ UpdateTime = table.Column(type: "datetime2", nullable: false),
+ CreateUserId = table.Column(type: "bigint", nullable: false),
+ UpdateUserId = table.Column(type: "bigint", nullable: false),
+ IsDeleted = table.Column(type: "bit", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Products", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "Users",
+ columns: table => new
+ {
+ Id = table.Column(type: "nvarchar(450)", nullable: false),
+ UserName = table.Column(type: "nvarchar(max)", nullable: true),
+ Password = table.Column(type: "nvarchar(max)", nullable: true),
+ Email = table.Column(type: "nvarchar(max)", nullable: true),
+ Phone = table.Column(type: "nvarchar(max)", nullable: true),
+ QrCode = table.Column(type: "nvarchar(max)", nullable: true),
+ CompanyCode = table.Column(type: "nvarchar(max)", nullable: true),
+ DeptCode = table.Column(type: "nvarchar(max)", nullable: true),
+ CreateTime = table.Column(type: "datetime2", nullable: false),
+ UpdateTime = table.Column(type: "datetime2", nullable: false),
+ CreateUserId = table.Column(type: "bigint", nullable: false),
+ UpdateUserId = table.Column(type: "bigint", nullable: false),
+ IsDeleted = table.Column(type: "bit", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Users", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "Posts",
+ columns: table => new
+ {
+ Id = table.Column(type: "nvarchar(450)", nullable: false),
+ Title = table.Column(type: "nvarchar(600)", maxLength: 600, nullable: true),
+ Content = table.Column(type: "nvarchar(max)", nullable: true),
+ BlogId = table.Column(type: "nvarchar(450)", nullable: true),
+ CreateTime = table.Column(type: "datetime2", nullable: false),
+ UpdateTime = table.Column(type: "datetime2", nullable: false),
+ CreateUserId = table.Column(type: "bigint", nullable: false),
+ UpdateUserId = table.Column(type: "bigint", nullable: false),
+ IsDeleted = table.Column(type: "bit", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Posts", x => x.Id);
+ table.ForeignKey(
+ name: "FK_Posts_Blog_BlogId",
+ column: x => x.BlogId,
+ principalTable: "Blog",
+ principalColumn: "Id");
+ });
+
+ migrationBuilder.CreateIndex(
+ name: "IX_Posts_BlogId",
+ table: "Posts",
+ column: "BlogId");
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropTable(
+ name: "Posts");
+
+ migrationBuilder.DropTable(
+ name: "Products");
+
+ migrationBuilder.DropTable(
+ name: "Users");
+
+ migrationBuilder.DropTable(
+ name: "Blog");
+ }
+ }
+}
diff --git a/Bunny.Common/Migrations/EfCoreContextModelSnapshot.cs b/Bunny.Common/Migrations/EfCoreContextModelSnapshot.cs
index 31a34f2..9663506 100644
--- a/Bunny.Common/Migrations/EfCoreContextModelSnapshot.cs
+++ b/Bunny.Common/Migrations/EfCoreContextModelSnapshot.cs
@@ -1,8 +1,9 @@
//
using System;
-using Bunny.Common.Connect;
+using Bunny.Common.Context;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
@@ -15,152 +16,164 @@ namespace Bunny.Common.Migrations
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
- modelBuilder.HasAnnotation("ProductVersion", "8.0.7");
+ modelBuilder
+ .HasAnnotation("ProductVersion", "8.0.8")
+ .HasAnnotation("Relational:MaxIdentifierLength", 128);
- modelBuilder.Entity("Bunny.Dao.Models.System.Blog", b =>
+ SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
+
+ modelBuilder.Entity("Bunny.Dao.Entity.System.Blog", b =>
{
b.Property("Id")
- .HasColumnType("TEXT");
+ .HasColumnType("nvarchar(450)");
b.Property("CreateTime")
- .HasColumnType("TEXT");
+ .HasColumnType("datetime2");
b.Property("CreateUserId")
- .HasColumnType("INTEGER");
+ .HasColumnType("bigint");
+
+ b.Property("IsDeleted")
+ .HasColumnType("bit");
b.Property("UpdateTime")
- .HasColumnType("TEXT");
+ .HasColumnType("datetime2");
b.Property("UpdateUserId")
- .HasColumnType("INTEGER");
+ .HasColumnType("bigint");
b.Property("Url")
.IsRequired()
- .HasColumnType("TEXT");
+ .HasColumnType("varchar(600)")
+ .HasColumnName("BlogUrl");
b.HasKey("Id");
- b.ToTable("Blogs");
+ b.ToTable("Blog");
});
- modelBuilder.Entity("Bunny.Dao.Models.System.Post", b =>
+ modelBuilder.Entity("Bunny.Dao.Entity.System.Post", b =>
{
b.Property("Id")
- .HasColumnType("TEXT");
+ .HasColumnType("nvarchar(450)");
- b.Property("BlogId")
- .HasColumnType("INTEGER");
-
- b.Property("BlogId1")
- .HasColumnType("TEXT");
+ b.Property("BlogId")
+ .HasColumnType("nvarchar(450)");
b.Property("Content")
- .HasColumnType("TEXT");
+ .HasColumnType("nvarchar(max)");
b.Property("CreateTime")
- .HasColumnType("TEXT");
+ .HasColumnType("datetime2");
b.Property("CreateUserId")
- .HasColumnType("INTEGER");
+ .HasColumnType("bigint");
- b.Property("PostId")
- .HasColumnType("INTEGER");
+ b.Property("IsDeleted")
+ .HasColumnType("bit");
b.Property("Title")
- .HasColumnType("TEXT");
+ .HasMaxLength(600)
+ .HasColumnType("nvarchar(600)");
b.Property("UpdateTime")
- .HasColumnType("TEXT");
+ .HasColumnType("datetime2");
b.Property("UpdateUserId")
- .HasColumnType("INTEGER");
+ .HasColumnType("bigint");
b.HasKey("Id");
- b.HasIndex("BlogId1");
+ b.HasIndex("BlogId");
b.ToTable("Posts");
});
- modelBuilder.Entity("Bunny.Dao.Models.System.Product", b =>
+ modelBuilder.Entity("Bunny.Dao.Entity.System.Product", b =>
{
b.Property("Id")
- .HasColumnType("TEXT");
+ .HasColumnType("nvarchar(450)");
b.Property("CreateTime")
- .HasColumnType("TEXT");
+ .HasColumnType("datetime2");
b.Property("CreateUserId")
- .HasColumnType("INTEGER");
+ .HasColumnType("bigint");
b.Property("CustomerId")
- .HasColumnType("TEXT");
+ .HasColumnType("nvarchar(max)");
b.Property("CustomerName")
- .HasColumnType("TEXT");
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("IsDeleted")
+ .HasColumnType("bit");
b.Property("PackageType")
- .HasColumnType("TEXT");
+ .HasColumnType("nvarchar(max)");
b.Property("UpdateTime")
- .HasColumnType("TEXT");
+ .HasColumnType("datetime2");
b.Property("UpdateUserId")
- .HasColumnType("INTEGER");
+ .HasColumnType("bigint");
b.HasKey("Id");
b.ToTable("Products");
});
- modelBuilder.Entity("Bunny.Dao.Models.System.User", b =>
+ modelBuilder.Entity("Bunny.Dao.Entity.System.User", b =>
{
b.Property("Id")
- .HasColumnType("TEXT");
+ .HasColumnType("nvarchar(450)");
b.Property("CompanyCode")
- .HasColumnType("TEXT");
+ .HasColumnType("nvarchar(max)");
b.Property("CreateTime")
- .HasColumnType("TEXT");
+ .HasColumnType("datetime2");
b.Property("CreateUserId")
- .HasColumnType("INTEGER");
+ .HasColumnType("bigint");
b.Property("DeptCode")
- .HasColumnType("TEXT");
+ .HasColumnType("nvarchar(max)");
b.Property("Email")
- .HasColumnType("TEXT");
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("IsDeleted")
+ .HasColumnType("bit");
b.Property("Password")
- .HasColumnType("TEXT");
+ .HasColumnType("nvarchar(max)");
b.Property("Phone")
- .HasColumnType("TEXT");
+ .HasColumnType("nvarchar(max)");
b.Property("QrCode")
- .HasColumnType("TEXT");
+ .HasColumnType("nvarchar(max)");
b.Property("UpdateTime")
- .HasColumnType("TEXT");
+ .HasColumnType("datetime2");
b.Property("UpdateUserId")
- .HasColumnType("INTEGER");
+ .HasColumnType("bigint");
b.Property("UserName")
- .HasColumnType("TEXT");
+ .HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("Users");
});
- modelBuilder.Entity("Bunny.Dao.Models.System.Post", b =>
+ modelBuilder.Entity("Bunny.Dao.Entity.System.Post", b =>
{
- b.HasOne("Bunny.Dao.Models.System.Blog", "Blog")
+ b.HasOne("Bunny.Dao.Entity.System.Blog", "Blog")
.WithMany()
- .HasForeignKey("BlogId1");
+ .HasForeignKey("BlogId");
b.Navigation("Blog");
});
diff --git a/Bunny.Common/Utils/EmailUtil.cs b/Bunny.Common/Utils/EmailUtil.cs
index be9398b..e410e7b 100644
--- a/Bunny.Common/Utils/EmailUtil.cs
+++ b/Bunny.Common/Utils/EmailUtil.cs
@@ -31,9 +31,9 @@ public class EmailUtil
};
// 判断是否有抄送
- if (entity.CC != null)
+ if (entity.Cc != null)
{
- var ccArray = entity.CC.Split(',');
+ var ccArray = entity.Cc.Split(',');
// 是抄送
if (entity.IsBbc == false)
foreach (var ccAddress in ccArray)
diff --git a/Bunny.Common/Utils/MinioUtil.cs b/Bunny.Common/Utils/MinioUtil.cs
index e23d2a9..c274b1f 100644
--- a/Bunny.Common/Utils/MinioUtil.cs
+++ b/Bunny.Common/Utils/MinioUtil.cs
@@ -1,4 +1,4 @@
-using Bunny.Common.Connect;
+using Bunny.Common.Context;
using Bunny.Common.Exception;
using Bunny.Dao.Model.Constant;
using Microsoft.AspNetCore.Http;
diff --git a/Bunny.Dao/Dto/System/BlogUpdateDto.cs b/Bunny.Dao/Dto/System/BlogUpdateDto.cs
new file mode 100644
index 0000000..1520cbf
--- /dev/null
+++ b/Bunny.Dao/Dto/System/BlogUpdateDto.cs
@@ -0,0 +1,20 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace Bunny.Dao.Dto.System;
+
+public class BlogUpdateDto
+{
+ [Required(ErrorMessage = "ID是必须的")] public Guid? Id { get; set; }
+ [Required(ErrorMessage = "Url是必填项")] public string? Url { get; init; }
+ public DateTime CreateTime { get; set; }
+
+ public DateTime UpdateTime { get; set; }
+
+ public long CreateUserId { get; set; }
+
+ public long UpdateUserId { get; set; }
+
+ public bool IsDeleted { get; set; }
+
+ public byte[]? Version { get; set; }
+}
\ No newline at end of file
diff --git a/Bunny.Dao/Entity/Base/BaseEntity.cs b/Bunny.Dao/Entity/Base/BaseEntity.cs
index 5875efc..4f32a97 100644
--- a/Bunny.Dao/Entity/Base/BaseEntity.cs
+++ b/Bunny.Dao/Entity/Base/BaseEntity.cs
@@ -1,8 +1,10 @@
-namespace Bunny.Dao.Entity.Base;
+using System.ComponentModel.DataAnnotations;
+
+namespace Bunny.Dao.Entity.Base;
public class BaseEntity
{
- public string? Id { get; set; }
+ [Key] public Guid? Id { get; set; }
public DateTime CreateTime { get; set; }
@@ -12,7 +14,7 @@ public class BaseEntity
public long UpdateUserId { get; set; }
- public string? OperationMessage { get; set; }
-
public bool IsDeleted { get; set; }
+
+ [Timestamp] public byte[]? Version { get; set; }
}
\ No newline at end of file
diff --git a/Bunny.Dao/Entity/Email/EmailSendEntity.cs b/Bunny.Dao/Entity/Email/EmailSendEntity.cs
index eb9c39e..cac4446 100644
--- a/Bunny.Dao/Entity/Email/EmailSendEntity.cs
+++ b/Bunny.Dao/Entity/Email/EmailSendEntity.cs
@@ -8,7 +8,7 @@ public abstract class EmailSendEntity
///
/// SMTP 服务器
///
- public string SmtpService { get; set; }
+ public string? SmtpService { get; set; }
///
/// SMTP 服务器端口号
@@ -18,32 +18,32 @@ public abstract class EmailSendEntity
///
/// 发送者邮件
///
- public string SendEmail { get; set; }
+ public string? SendEmail { get; set; }
///
/// 发送者密码
///
- public string SendEmailPassword { get; set; }
+ public string? SendEmailPassword { get; set; }
///
/// 接受这邮件
///
- public string ReceiverEmail { get; set; }
+ public string? ReceiverEmail { get; set; }
///
/// 发送邮件的主题
///
- public string Subject { get; set; }
+ public string? Subject { get; set; }
///
/// 发送邮件的内容
///
- public string Body { get; set; }
+ public string? Body { get; set; }
///
/// 设置抄送
///
- public string? CC { get; set; }
+ public string? Cc { get; set; }
///
/// 是否密送
diff --git a/Bunny.Dao/Entity/System/Blog.cs b/Bunny.Dao/Entity/System/Blog.cs
index 516e119..b373b42 100644
--- a/Bunny.Dao/Entity/System/Blog.cs
+++ b/Bunny.Dao/Entity/System/Blog.cs
@@ -1,9 +1,13 @@
using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
using Bunny.Dao.Entity.Base;
namespace Bunny.Dao.Entity.System;
+[Table("Blog")]
public class Blog : BaseEntity
{
- [Required(ErrorMessage = "邮箱是必填项")] public string Url { get; set; }
+ [Required]
+ [Column("BlogUrl", TypeName = "varchar(600)")]
+ public string? Url { get; init; }
}
\ No newline at end of file
diff --git a/Bunny.Dao/Entity/System/Post.cs b/Bunny.Dao/Entity/System/Post.cs
index 7d556a6..e0d22ca 100644
--- a/Bunny.Dao/Entity/System/Post.cs
+++ b/Bunny.Dao/Entity/System/Post.cs
@@ -1,13 +1,11 @@
-using Bunny.Dao.Entity.Base;
+using System.ComponentModel.DataAnnotations;
+using Bunny.Dao.Entity.Base;
namespace Bunny.Dao.Entity.System;
public class Post : BaseEntity
{
- public int PostId { get; set; }
- public string? Title { get; set; }
- public string? Content { get; set; }
-
- public int BlogId { get; set; }
- public Blog? Blog { get; set; }
+ [MaxLength(600)] public string? Title { get; init; }
+ public string? Content { get; init; }
+ public Blog? Blog { get; init; }
}
\ No newline at end of file
diff --git a/Bunny.Dao/Model/Constant/ExceptionConstant.cs b/Bunny.Dao/Model/Constant/ExceptionConstant.cs
index e6bbae8..41e844f 100644
--- a/Bunny.Dao/Model/Constant/ExceptionConstant.cs
+++ b/Bunny.Dao/Model/Constant/ExceptionConstant.cs
@@ -14,6 +14,7 @@ public class ExceptionConstant
public const string AddDataIsEmptyException = "添加数据为空";
public const string DeleteIdIsNotEmptyException = "删除id不能为空";
public const string ServerError = "服务器错误";
+ public const string DataBaseError = "数据库错误";
// 文章操作相关
public const string DoLikeCommentNotExist = "点赞内容不存在";
diff --git a/Bunny.Dao/Model/Result/Result.cs b/Bunny.Dao/Model/Result/Result.cs
index 945b0dc..63c5082 100644
--- a/Bunny.Dao/Model/Result/Result.cs
+++ b/Bunny.Dao/Model/Result/Result.cs
@@ -168,7 +168,7 @@ public class Result(HttpStatusCode code, T? data, string? message)
/// 消息内容
/// 数据内容分
/// 返回的数据内容
- public static Result Error(string message, T data)
+ public static Result Error(T data, string message)
{
return new Result(HttpStatusCode.InternalServerError, data, message);
}
diff --git a/Bunny.Service/IService/IBlogService.cs b/Bunny.Service/IService/IBlogService.cs
index c4da136..2f46545 100644
--- a/Bunny.Service/IService/IBlogService.cs
+++ b/Bunny.Service/IService/IBlogService.cs
@@ -1,4 +1,5 @@
-using Bunny.Dao.Entity.System;
+using Bunny.Dao.Dto.System;
+using Bunny.Dao.Entity.System;
using Bunny.Dao.Model.Result;
namespace Bunny.Service.IService;
@@ -21,7 +22,7 @@ public interface IBlogService
/// 更新Blog内容
///
///
- void UpdateBlog(Blog dto);
+ void UpdateBlog(BlogUpdateDto dto);
///
/// 删除BLog
diff --git a/Bunny.Service/IService/Service/BlogService.cs b/Bunny.Service/IService/Service/BlogService.cs
index 3344376..9ee6589 100644
--- a/Bunny.Service/IService/Service/BlogService.cs
+++ b/Bunny.Service/IService/Service/BlogService.cs
@@ -1,17 +1,15 @@
-using Bunny.Common.Connect;
+using Bunny.Common.Context;
+using Bunny.Common.Utils.Net;
+using Bunny.Dao.Dto.System;
using Bunny.Dao.Entity.System;
using Bunny.Dao.Model.Result;
+using Microsoft.AspNetCore.Components;
namespace Bunny.Service.IService.Service;
public class BlogService : IBlogService
{
- private readonly EfCoreContext _dbContext;
-
- public BlogService(EfCoreContext dbContext)
- {
- _dbContext = dbContext;
- }
+ [Inject] public required EfCoreContext DbContext { get; set; }
///
/// 添加Blog
@@ -20,8 +18,8 @@ public class BlogService : IBlogService
///
public void AddBlog(Blog dto)
{
- _dbContext.Add(dto);
- _dbContext.SaveChanges();
+ DbContext.Add(dto);
+ DbContext.SaveChanges();
}
///
@@ -30,17 +28,20 @@ public class BlogService : IBlogService
///
public List QueryBlog()
{
- return _dbContext.Blogs.ToList();
+ return DbContext.Blogs.ToList();
}
///
/// 更新Blog内容
///
///
- public void UpdateBlog(Blog dto)
+ public void UpdateBlog(BlogUpdateDto dto)
{
- _dbContext.Blogs.Update(dto);
- _dbContext.SaveChanges();
+ var blog = new Blog();
+ NetUtil.CopyProperties(dto, blog);
+
+ DbContext.Blogs.Update(blog);
+ DbContext.SaveChanges();
}
///
@@ -49,9 +50,9 @@ public class BlogService : IBlogService
///
public void DeleteBlog(string id)
{
- var blog = new Blog { Id = id };
- _dbContext.Blogs.Remove(blog);
- _dbContext.SaveChanges();
+ var blog = new Blog { Id = Guid.NewGuid() };
+ DbContext.Blogs.Remove(blog);
+ DbContext.SaveChanges();
}
///
@@ -64,7 +65,6 @@ public class BlogService : IBlogService
for (var i = 0; i <= 100000; i++)
list.Add(new Blog
{
- Id = $"{i}",
Url = url,
CreateTime = DateTime.Now,
UpdateTime = DateTime.Now,
@@ -72,8 +72,8 @@ public class BlogService : IBlogService
CreateUserId = Random.Shared.NextInt64()
});
- _dbContext.Blogs.AddRange(list);
- _dbContext.SaveChanges();
+ DbContext.Blogs.AddRange(list);
+ DbContext.SaveChanges();
}
@@ -85,12 +85,12 @@ public class BlogService : IBlogService
var list = new List();
for (var i = 0; i < 10; i++)
{
- var blog = new Blog { Id = $"{i}" };
+ var blog = new Blog();
list.Add(blog);
}
- _dbContext.Blogs.RemoveRange(list);
- _dbContext.SaveChanges();
+ DbContext.Blogs.RemoveRange(list);
+ DbContext.SaveChanges();
}
///
@@ -99,19 +99,19 @@ public class BlogService : IBlogService
public void UseTransaction()
{
// 还可以使用异步的
- var transaction = _dbContext.Database.BeginTransaction();
+ var transaction = DbContext.Database.BeginTransaction();
// 执行批量更新操作
var list = new List();
for (var i = 0; i < 10; i++)
{
- var blog = new Blog { Id = $"{i}", Url = "https://learn.microsoft.com/zh-cn/ef/core/saving/transactions" };
+ var blog = new Blog { Url = "https://learn.microsoft.com/zh-cn/ef/core/saving/transactions" };
list.Add(blog);
}
// 更新内容
- _dbContext.Blogs.UpdateRange(list);
- _dbContext.SaveChanges();
+ DbContext.Blogs.UpdateRange(list);
+ DbContext.SaveChanges();
// 还可以使用异步方式
transaction.Commit();
@@ -124,7 +124,7 @@ public class BlogService : IBlogService
///
public PageResult QueryPage(int page, int limit)
{
- var items = _dbContext.Blogs.ToList();
+ var items = DbContext.Blogs.Take(limit).Skip(page).ToList();
var total = items.Count;
var pages = (int)Math.Ceiling(total / (double)limit);
diff --git a/Bunny.Service/IService/Service/JobService.cs b/Bunny.Service/IService/Service/JobService.cs
index 0924f09..3a60d3b 100644
--- a/Bunny.Service/IService/Service/JobService.cs
+++ b/Bunny.Service/IService/Service/JobService.cs
@@ -13,7 +13,6 @@ public class JobService : IJobService
public void StartSimpleJob()
{
var schedulerFactory = new StdSchedulerFactory();
- // TODO 如果使用异步,必须使用await 和 async
// var scheduler = schedulerFactory.GetScheduler();
var scheduler = schedulerFactory.GetScheduler().GetAwaiter().GetResult();
@@ -32,10 +31,6 @@ public class JobService : IJobService
// 使用同步方法
scheduler.ScheduleJob(jobDetail, trigger).GetAwaiter().GetResult();
scheduler.Start().GetAwaiter().GetResult();
-
- // TODO 使用异步
- // await _scheduler.ScheduleJob(jobDetail, trigger);
- // await _scheduler.Start();
}
///
@@ -49,8 +44,8 @@ public class JobService : IJobService
var jobDetail = JobBuilder.Create()
.UsingJobData("username", "用户名")
.UsingJobData("password", "密码")
- // TODO 如果不设置持久的会报错;
- // TODO Jobs added with no trigger must be durable.Quartz.SchedulerException: Jobs added with no trigger must be durable.
+ // 如果不设置持久的会报错;
+ // Jobs added with no trigger must be durable.Quartz.SchedulerException: Jobs added with no trigger must be durable.
.StoreDurably() // 设置作业为持久的
.WithIdentity("simpleJob", "简单的JOB")
.Build();
@@ -63,9 +58,9 @@ public class JobService : IJobService
.UsingJobData("trigger", "trigger值")
.WithIdentity("testTrigger", "测试发出器")
.StartNow()
- // TODO 设置调度时间单位
+ // 设置调度时间单位
// .WithSimpleSchedule(x => x.WithIntervalInSeconds(1).WithRepeatCount(10))
- // TODO 自定义调度时间单位
+ // 自定义调度时间单位
.WithSimpleSchedule(x => x.WithInterval(TimeSpan.FromMinutes(1)).WithRepeatCount(10))
.Build();
@@ -95,9 +90,9 @@ public class JobService : IJobService
.UsingJobData("trigger", "trigger值")
.WithIdentity("testTrigger", "测试发出器")
.StartNow()
- // TODO StartingDailyAt(TimeOfDay.HourAndMinuteOfDay(20, 0)):触发器从每天的20:00(晚上8点)开始。
- // TODO EndingDailyAt(TimeOfDay.HourAndMinuteOfDay(22, 0)):触发器在每天的22:00(晚上10点)结束。
- // TODO WithIntervalInSeconds(2):在开始和结束时间之间,触发器将每2秒触发一次作业。
+ // StartingDailyAt(TimeOfDay.HourAndMinuteOfDay(20, 0)):触发器从每天的20:00(晚上8点)开始。
+ // EndingDailyAt(TimeOfDay.HourAndMinuteOfDay(22, 0)):触发器在每天的22:00(晚上10点)结束。
+ // WithIntervalInSeconds(2):在开始和结束时间之间,触发器将每2秒触发一次作业。
.WithDailyTimeIntervalSchedule(x => x.StartingDailyAt(TimeOfDay.HourAndMinuteOfDay(16, 0))
.EndingDailyAt(TimeOfDay.HourAndMinuteOfDay(22, 0))
// 设置工作时间在每周的星期几
diff --git a/Bunny.Service/IService/Service/MinioService.cs b/Bunny.Service/IService/Service/MinioService.cs
index a4f0c23..d41e168 100644
--- a/Bunny.Service/IService/Service/MinioService.cs
+++ b/Bunny.Service/IService/Service/MinioService.cs
@@ -1,5 +1,5 @@
using Bunny.Common;
-using Bunny.Common.Connect;
+using Bunny.Common.Context;
using Microsoft.AspNetCore.Http;
using Minio;
using Minio.DataModel;
diff --git a/Bunny.Service/IService/Service/RedisOptionService.cs b/Bunny.Service/IService/Service/RedisOptionService.cs
index 53b003e..31f7926 100644
--- a/Bunny.Service/IService/Service/RedisOptionService.cs
+++ b/Bunny.Service/IService/Service/RedisOptionService.cs
@@ -1,4 +1,4 @@
-using Bunny.Common.Connect;
+using Bunny.Common.Context;
using Bunny.Dao.Entity.System;
using Newtonsoft.Json;
using StackExchange.Redis;
@@ -7,7 +7,7 @@ namespace Bunny.Service.IService.Service;
public class RedisOptionService : IRedisOptionService
{
- private readonly IDatabase _redisDatabase = RedisContext.RedisDatabase;
+ private readonly IDatabase _redisDatabase = RedisContext.RedisDatabase!;
///
@@ -60,7 +60,7 @@ public class RedisOptionService : IRedisOptionService
{
var post = new Post
{
- PostId = 1,
+ Id = Guid.NewGuid(),
Title = "存入JSON内容",
Content = "正在存入JSON内容"
};
diff --git a/Bunny.Service/WebSocket/WebSocketTest.cs b/Bunny.Service/WebSocket/WebSocketTest.cs
index 4c3fd6f..10f6879 100644
--- a/Bunny.Service/WebSocket/WebSocketTest.cs
+++ b/Bunny.Service/WebSocket/WebSocketTest.cs
@@ -6,7 +6,7 @@ public static class WebSocketTest
{
public static void Start()
{
- var webSocketServer = new WebSocketServer("ws://0.0.0.0:8000");
+ var webSocketServer = new WebSocketServer("ws://0.0.0.0:8800");
webSocketServer.RestartAfterListenError = true;
webSocketServer.Start(socket =>
diff --git a/Bunny.Test.Until/EfCoreTest/EfCoreTest.cs b/Bunny.Test.Until/EfCoreTest/EfCoreTest.cs
deleted file mode 100644
index 19f8e94..0000000
--- a/Bunny.Test.Until/EfCoreTest/EfCoreTest.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using Bunny.Common.Connect;
-using Bunny.Dao.Entity.System;
-using NUnit.Framework;
-
-namespace Bunny.Test.Until.EfCoreTest;
-
-public class EfCoreTest
-{
- [Test]
- public void TestDbConnection()
- {
- using var db = new EfCoreContext();
- Console.WriteLine($"Database path: {db.DbPath}.");
-
- // Create
- Console.WriteLine("Inserting a new blog");
- db.Add(new Blog { Url = "http://blogs.msdn.com/adonet" });
- db.SaveChanges();
-
- // Read
- Console.WriteLine("Querying for a blog");
- var blog = db.Blogs
- .OrderBy(b => b.Id)
- .First();
- Console.WriteLine(blog.Url);
- }
-}
\ No newline at end of file
diff --git a/Bunny.WebApi/Bunny.WebApi.csproj b/Bunny.WebApi/Bunny.WebApi.csproj
index fffaba7..70cb8d7 100644
--- a/Bunny.WebApi/Bunny.WebApi.csproj
+++ b/Bunny.WebApi/Bunny.WebApi.csproj
@@ -27,6 +27,8 @@
+
+
diff --git a/Bunny.WebApi/Configuration/AddAutofacConfig.cs b/Bunny.WebApi/Configuration/AddAutofacConfig.cs
new file mode 100644
index 0000000..5ec4f8b
--- /dev/null
+++ b/Bunny.WebApi/Configuration/AddAutofacConfig.cs
@@ -0,0 +1,32 @@
+using Autofac;
+using Bunny.Common.Context;
+using Bunny.Service.IService;
+using Bunny.Service.IService.Service;
+using Microsoft.AspNetCore.Mvc;
+
+namespace Bunny.WebApi.Configuration;
+
+public static class AddAutofacConfig
+{
+ public static void BuildContainer(ContainerBuilder builder)
+ {
+ // 异步方式创建数据库
+ new EfCoreContext().Database.EnsureCreatedAsync();
+
+ // 如果不在在 Controller 层写构造函数可以打开这个,自动完成注入
+ var controllerBaseType = typeof(ControllerBase);
+ builder.RegisterAssemblyTypes(typeof(Program).Assembly)
+ .Where(t => controllerBaseType.IsAssignableFrom(t) && t != controllerBaseType)
+ .PropertiesAutowired(); //支持属性注入
+
+ // 注入EfCore上下文对象
+ builder.RegisterType();
+
+ // 注入Service服务
+ builder.RegisterType().As();
+ builder.RegisterType().As();
+ builder.RegisterType().As();
+ builder.RegisterType().As();
+ builder.RegisterType().As();
+ }
+}
\ No newline at end of file
diff --git a/Bunny.WebApi/Config/BaseConfig.cs b/Bunny.WebApi/Configuration/BaseConfig.cs
similarity index 69%
rename from Bunny.WebApi/Config/BaseConfig.cs
rename to Bunny.WebApi/Configuration/BaseConfig.cs
index 9051a78..7b3bb6d 100644
--- a/Bunny.WebApi/Config/BaseConfig.cs
+++ b/Bunny.WebApi/Configuration/BaseConfig.cs
@@ -1,9 +1,12 @@
-using Bunny.Common;
-using Bunny.Common.Configuration;
-using Bunny.Common.Connect;
+using Autofac;
+using Autofac.Extensions.DependencyInjection;
+using Bunny.Common;
+using Bunny.Common.Context;
using Bunny.Service.WebSocket;
+using Microsoft.AspNetCore.Mvc.Controllers;
+using Microsoft.Extensions.DependencyInjection.Extensions;
-namespace Bunny.WebApi.Config;
+namespace Bunny.WebApi.Configuration;
public class BaseConfig(WebApplicationBuilder builder)
{
@@ -12,24 +15,25 @@ public class BaseConfig(WebApplicationBuilder builder)
///
public void Initialize()
{
- // 配置跨域
+ // 配置跨域
UseCors();
// 配置日志相关
- // builder.Logging.AddLog4Net("Config/log4net.config");
+ // builder.Logging.AddLog4Net("Configuration/log4net.config");
// 自定义时间格式
builder.Services.AddControllers().AddJsonOptions(options =>
options.JsonSerializerOptions.Converters.Add(new JsonDateTimeConverter()));
// 添加使用自定义配置文件
builder.Services.AddSingleton(new AppSettings(builder.Configuration));
- // 添加 SignalR
- builder.Services.AddSignalR();
builder.WebHost.ConfigureKestrel((_, options) =>
{
// 设置文件最大上传大小
options.Limits.MaxRequestBodySize = 1024 * 1024 * 100;
});
- // 添加Service服务
- builder.AddApplicationServices();
+ // 使用 AddAutofac 注册服务
+ builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
+ builder.Host.ConfigureContainer(AddAutofacConfig.BuildContainer);
+ // 让控制器实例由容器创建
+ builder.Services.Replace(ServiceDescriptor.Transient());
// 添加定时任务
builder.AddApplicationBackendServices();
// 设置过滤器
diff --git a/Bunny.WebApi/Config/Knife4Net.cs b/Bunny.WebApi/Configuration/Knife4Net.cs
similarity index 96%
rename from Bunny.WebApi/Config/Knife4Net.cs
rename to Bunny.WebApi/Configuration/Knife4Net.cs
index 4272698..9187af2 100644
--- a/Bunny.WebApi/Config/Knife4Net.cs
+++ b/Bunny.WebApi/Configuration/Knife4Net.cs
@@ -1,7 +1,7 @@
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.OpenApi.Models;
-namespace Bunny.WebApi.Config;
+namespace Bunny.WebApi.Configuration;
public static class Knife4Net
{
diff --git a/Bunny.WebApi/Config/ServiceRegistration.cs b/Bunny.WebApi/Configuration/ServiceRegistration.cs
similarity index 78%
rename from Bunny.WebApi/Config/ServiceRegistration.cs
rename to Bunny.WebApi/Configuration/ServiceRegistration.cs
index 770f699..0ea49ad 100644
--- a/Bunny.WebApi/Config/ServiceRegistration.cs
+++ b/Bunny.WebApi/Configuration/ServiceRegistration.cs
@@ -1,30 +1,14 @@
-using Bunny.Common.Connect;
-using Bunny.Common.Filter;
+using Bunny.Common.Filter;
using Bunny.Service.Filter;
-using Bunny.Service.IService;
-using Bunny.Service.IService.Service;
using Bunny.Service.Job.JobService;
using Lazy.Captcha.Core;
using Lazy.Captcha.Core.Generator;
using SkiaSharp;
-namespace Bunny.WebApi.Config;
+namespace Bunny.WebApi.Configuration;
public static class ServiceRegistration
{
- public static void AddApplicationServices(this WebApplicationBuilder builder)
- {
- // 注入EfCore上下文对象
- builder.Services.AddScoped();
-
- // 注入Service服务
- builder.Services.AddScoped();
- builder.Services.AddScoped();
- builder.Services.AddScoped();
- builder.Services.AddScoped();
- builder.Services.AddScoped();
- }
-
///
/// 注入后台服务相关
/// 用于添加所以Job服务,之后在BaseConfig中进行调用
diff --git a/Bunny.WebApi/Config/log4net.config b/Bunny.WebApi/Configuration/log4net.config
similarity index 100%
rename from Bunny.WebApi/Config/log4net.config
rename to Bunny.WebApi/Configuration/log4net.config
diff --git a/Bunny.WebApi/Controllers/BlogController.cs b/Bunny.WebApi/Controllers/BlogController.cs
index 01c8c67..887425a 100644
--- a/Bunny.WebApi/Controllers/BlogController.cs
+++ b/Bunny.WebApi/Controllers/BlogController.cs
@@ -1,6 +1,8 @@
-using Bunny.Dao.Entity.System;
+using Bunny.Dao.Dto.System;
+using Bunny.Dao.Entity.System;
using Bunny.Dao.Model.Result;
using Bunny.Service.IService;
+using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Mvc;
namespace Bunny.WebApi.Controllers;
@@ -8,15 +10,10 @@ namespace Bunny.WebApi.Controllers;
///
/// BLog相关接口
///
-[Route("/api/[controller]/[action]")]
+[Microsoft.AspNetCore.Mvc.Route("/api/[controller]/[action]")]
public class BlogController : ControllerBase
{
- private readonly IBlogService _blogService;
-
- public BlogController(IBlogService blogService)
- {
- _blogService = blogService;
- }
+ [Inject] public required IBlogService BlogService { get; set; }
///
/// 添加Blog
@@ -26,7 +23,7 @@ public class BlogController : ControllerBase
[HttpPost]
public Result