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 AddBlog(Blog dto) { - _blogService.AddBlog(dto); + BlogService.AddBlog(dto); return Result.Success(); } @@ -37,7 +34,7 @@ public class BlogController : ControllerBase [HttpGet] public Result> QueryBlog() { - var vo = _blogService.QueryBlog(); + var vo = BlogService.QueryBlog(); return Result>.Success(vo); } @@ -47,9 +44,9 @@ public class BlogController : ControllerBase /// /// [HttpPost] - public Result UpdateBlog(Blog dto) + public Result UpdateBlog(BlogUpdateDto dto) { - _blogService.UpdateBlog(dto); + BlogService.UpdateBlog(dto); return Result.Success(); } @@ -60,7 +57,7 @@ public class BlogController : ControllerBase [HttpDelete] public Result DeleteBlog(string id) { - _blogService.DeleteBlog(id); + BlogService.DeleteBlog(id); return Result.Success(); } @@ -71,7 +68,7 @@ public class BlogController : ControllerBase [HttpPost] public Result AddBatchBlogs(string url) { - _blogService.AddBatchBlogs(url); + BlogService.AddBatchBlogs(url); return Result.Success(); } @@ -82,7 +79,7 @@ public class BlogController : ControllerBase [HttpGet] public Result DeleteBatchBlogs() { - _blogService.DeleteBatchBlogs(); + BlogService.DeleteBatchBlogs(); return Result.Success(); } @@ -93,7 +90,7 @@ public class BlogController : ControllerBase [HttpGet] public Result UseTransaction() { - _blogService.UseTransaction(); + BlogService.UseTransaction(); return Result.Success(); } @@ -104,7 +101,7 @@ public class BlogController : ControllerBase [HttpPost] public Result> QueryPage(int page = 1, int limit = 10) { - var vo = _blogService.QueryPage(page, limit); + var vo = BlogService.QueryPage(page, limit); return Result>.Success(vo); } diff --git a/Bunny.WebApi/Controllers/CaptchaTestController.cs b/Bunny.WebApi/Controllers/CaptchaTestController.cs index 33abe87..6bebf50 100644 --- a/Bunny.WebApi/Controllers/CaptchaTestController.cs +++ b/Bunny.WebApi/Controllers/CaptchaTestController.cs @@ -1,6 +1,7 @@ using Bunny.Dao.Model.Constant.Result; using Bunny.Dao.Model.Result; using Lazy.Captcha.Core; +using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Mvc; namespace Bunny.WebApi.Controllers; @@ -8,9 +9,11 @@ namespace Bunny.WebApi.Controllers; /// /// 验证码测试 /// -[Route("/api/[controller]/[action]")] -public class CaptchaTestController(ICaptcha _captcha) : ControllerBase +[Microsoft.AspNetCore.Mvc.Route("/api/[controller]/[action]")] +public class CaptchaTestController : ControllerBase { + [Inject] public required ICaptcha Captcha { get; set; } + /// /// 测试测试验证码生成 /// @@ -18,7 +21,7 @@ public class CaptchaTestController(ICaptcha _captcha) : ControllerBase [HttpGet] public IActionResult GetCaptcha(string id) { - var captchaData = _captcha.Generate(id); + var captchaData = Captcha.Generate(id); // 验证码的ID var captchaDataId = captchaData.Id; // 验证码的代码 @@ -39,7 +42,9 @@ public class CaptchaTestController(ICaptcha _captcha) : ControllerBase public Result CheckCode(string id, string code) { // 校验用户输入的验证码是否=正确 - var validate = _captcha.Validate(id, code); - return validate ? Result.Success() : Result.Error(ErrorConstant.ValidateCodeError); + var validate = Captcha.Validate(id, code); + return validate + ? Result.Success() + : Result.Error(null!, ErrorConstant.ValidateCodeError); } } \ No newline at end of file diff --git a/Bunny.WebApi/Controllers/JobInitController.cs b/Bunny.WebApi/Controllers/JobInitController.cs index e37335f..2b54ea6 100644 --- a/Bunny.WebApi/Controllers/JobInitController.cs +++ b/Bunny.WebApi/Controllers/JobInitController.cs @@ -1,5 +1,6 @@ using Bunny.Dao.Model.Result; using Bunny.Service.IService; +using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Mvc; namespace Bunny.WebApi.Controllers; @@ -7,9 +8,11 @@ namespace Bunny.WebApi.Controllers; /// /// Quartz 示例相关 /// -[Route("/api/[controller]/[action]")] -public class JobInitController(IJobService jobService) : ControllerBase +[Microsoft.AspNetCore.Mvc.Route("/api/[controller]/[action]")] +public class JobInitController : ControllerBase { + [Inject] public required IJobService JobService { get; set; } + /// /// 1. 开启一个简单的工作 /// @@ -17,7 +20,7 @@ public class JobInitController(IJobService jobService) : ControllerBase [HttpPost] public Result StartSimpleJob() { - jobService.StartSimpleJob(); + JobService.StartSimpleJob(); return Result.Success("将名称生成放在jobDetail中,可以再运行时获取到"); } @@ -28,7 +31,7 @@ public class JobInitController(IJobService jobService) : ControllerBase [HttpPost] public Result PutJobDetail4Trigger() { - jobService.PutJobDetail4Trigger(); + JobService.PutJobDetail4Trigger(); return Result.Success("将jobDetail中的一些信息放在触发器中,简化写法"); } @@ -39,7 +42,7 @@ public class JobInitController(IJobService jobService) : ControllerBase [HttpHead] public Result SetJobWithDaily() { - jobService.SetJobWithDaily(); + JobService.SetJobWithDaily(); return Result.Success(); } } \ No newline at end of file diff --git a/Bunny.WebApi/Controllers/MinioController.cs b/Bunny.WebApi/Controllers/MinioController.cs index a289ca3..44b1bb9 100644 --- a/Bunny.WebApi/Controllers/MinioController.cs +++ b/Bunny.WebApi/Controllers/MinioController.cs @@ -1,15 +1,18 @@ using Bunny.Dao.Model.Result; using Bunny.Service.IService; +using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Mvc; using Minio.DataModel; using Minio.DataModel.Result; namespace Bunny.WebApi.Controllers; -[Route("/api/[controller]/[action]")] +[Microsoft.AspNetCore.Mvc.Route("/api/[controller]/[action]")] [ApiController] -public class MinioController(IMinioService minioService) : ControllerBase +public class MinioController : ControllerBase { + [Inject] public required IMinioService MinioService { get; set; } + /// /// 查询所有的桶 /// @@ -17,7 +20,7 @@ public class MinioController(IMinioService minioService) : ControllerBase [HttpGet] public Result GetAllMyBuckets() { - var listAllMyBucketsResult = minioService.GetAllMyBuckets(); + var listAllMyBucketsResult = MinioService.GetAllMyBuckets(); return Result.Success(listAllMyBucketsResult); } @@ -29,7 +32,7 @@ public class MinioController(IMinioService minioService) : ControllerBase [HttpPost] public Result SaveMinioFile(IFormFile? file, string filepath = "test") { - minioService.SaveMinioFile(file, filepath); + MinioService.SaveMinioFile(file, filepath); return Result.Success("上传成功"); } @@ -42,7 +45,7 @@ public class MinioController(IMinioService minioService) : ControllerBase [HttpGet] public Result GetObjectStat(string filename, string bucketName = "csharp-test") { - var vo = minioService.GetObjectStat(filename, bucketName); + var vo = MinioService.GetObjectStat(filename, bucketName); return Result.Success(vo); } @@ -55,7 +58,7 @@ public class MinioController(IMinioService minioService) : ControllerBase [HttpGet] public Result GetObjectPath(string filename, string bucketName = "csharp-test") { - var vo = minioService.GetObjectPath(filename, bucketName); + var vo = MinioService.GetObjectPath(filename, bucketName); return Result.Success(vo); } @@ -68,7 +71,7 @@ public class MinioController(IMinioService minioService) : ControllerBase [HttpGet] public IActionResult DownloadObject(string filename, string bucketName = "csharp-test") { - var buffer = minioService.DownloadObject(filename, bucketName).Result; + var buffer = MinioService.DownloadObject(filename, bucketName).Result; return File(buffer, "application/octet-stream", filename); } @@ -81,7 +84,7 @@ public class MinioController(IMinioService minioService) : ControllerBase [HttpGet] public IActionResult ViewObject(string filename, string bucketName = "csharp-test") { - var buffer = minioService.DownloadObject(filename, bucketName).Result; + var buffer = MinioService.DownloadObject(filename, bucketName).Result; return File(buffer, "image/jpeg"); } @@ -94,7 +97,7 @@ public class MinioController(IMinioService minioService) : ControllerBase [HttpGet] public Result> ListObject(string? filepath, string bucketName = "csharp-test") { - var vo = minioService.ListObject(filepath, bucketName); + var vo = MinioService.ListObject(filepath, bucketName); return Result>.Success(vo); } } \ No newline at end of file diff --git a/Bunny.WebApi/Controllers/RedisController.cs b/Bunny.WebApi/Controllers/RedisController.cs index 4a08823..7591ca4 100644 --- a/Bunny.WebApi/Controllers/RedisController.cs +++ b/Bunny.WebApi/Controllers/RedisController.cs @@ -1,5 +1,6 @@ using Bunny.Dao.Model.Result; using Bunny.Service.IService; +using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Mvc; namespace Bunny.WebApi.Controllers; @@ -7,15 +8,10 @@ namespace Bunny.WebApi.Controllers; /// /// 操作Redis相关内容 /// -[Route("/api/[controller]/[action]")] +[Microsoft.AspNetCore.Mvc.Route("/api/[controller]/[action]")] public class RedisOptionController : ControllerBase { - private readonly IRedisOptionService _redisOptionService; - - public RedisOptionController(IRedisOptionService redisOptionService) - { - _redisOptionService = redisOptionService; - } + [Inject] public required IRedisOptionService RedisOptionService { get; set; } /// /// 添加Redis中一个值 @@ -26,7 +22,7 @@ public class RedisOptionController : ControllerBase [HttpPost] public Result AddStringValue(string key, string value) { - _redisOptionService.AddStringValue(key, value); + RedisOptionService.AddStringValue(key, value); return Result.Success(); } @@ -37,7 +33,7 @@ public class RedisOptionController : ControllerBase [HttpPost] public Result QueryStringKey(string key) { - var queryStringKey = _redisOptionService.QueryStringKey(key); + var queryStringKey = RedisOptionService.QueryStringKey(key); return Result.Success(queryStringKey); } @@ -50,7 +46,7 @@ public class RedisOptionController : ControllerBase [HttpPost] public Result AddTimeRedisKey(string key, string value) { - _redisOptionService.AddTimeRedisKey(key, value); + RedisOptionService.AddTimeRedisKey(key, value); return Result.Success(value); } @@ -63,7 +59,7 @@ public class RedisOptionController : ControllerBase [HttpPost] public Result AddTimeRedisKeyTtl(string key, string value) { - _redisOptionService.AddTimeRedisKeyTtl(key, value); + RedisOptionService.AddTimeRedisKeyTtl(key, value); return Result.Success(value); } @@ -74,7 +70,7 @@ public class RedisOptionController : ControllerBase [HttpGet] public Result AddJson() { - var json = _redisOptionService.AddJson(); + var json = RedisOptionService.AddJson(); return Result.Success(json); } @@ -86,7 +82,7 @@ public class RedisOptionController : ControllerBase [HttpDelete] public Result DeleteKey(string key) { - _redisOptionService.DeleteKey(key); + RedisOptionService.DeleteKey(key); return Result.Success(); } @@ -97,7 +93,7 @@ public class RedisOptionController : ControllerBase [HttpPost] public Result SetRedisCreateTransaction(string key, string value) { - var redisCreateTransaction = _redisOptionService.SetRedisCreateTransaction(key, value); + var redisCreateTransaction = RedisOptionService.SetRedisCreateTransaction(key, value); return Result.Success(redisCreateTransaction); } @@ -108,7 +104,7 @@ public class RedisOptionController : ControllerBase [HttpPost] public Result AddHashWithRedis(string key, double keyExpire = 6.0) { - _redisOptionService.AddHashWithRedis(key, keyExpire); + RedisOptionService.AddHashWithRedis(key, keyExpire); return Result.Success(); } } \ No newline at end of file diff --git a/Bunny.WebApi/Controllers/TemplateController.cs b/Bunny.WebApi/Controllers/TemplateController.cs index a6a223c..c425f52 100644 --- a/Bunny.WebApi/Controllers/TemplateController.cs +++ b/Bunny.WebApi/Controllers/TemplateController.cs @@ -1,5 +1,6 @@ using Bunny.Dao.Model.Result; using Bunny.Service.IService; +using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Mvc; namespace Bunny.WebApi.Controllers; @@ -8,15 +9,10 @@ namespace Bunny.WebApi.Controllers; /// 测试请求模板 /// [ApiController] -[Route("api/[controller]")] +[Microsoft.AspNetCore.Mvc.Route("api/[controller]")] public class TemplateController : ControllerBase { - private readonly IBaseService _baseService; - - public TemplateController(IBaseService baseService) - { - _baseService = baseService; - } + [Inject] public required IBaseService BaseService { get; set; } /// /// 测试走缓存 @@ -36,7 +32,7 @@ public class TemplateController : ControllerBase [HttpGet("TestInject")] public Result TestInject() { - var testIndex = _baseService.TestIndex(); + var testIndex = BaseService.TestIndex(); return Result.Success(testIndex); } } \ No newline at end of file diff --git a/Bunny.WebApi/Database/bunny.db b/Bunny.WebApi/Database/bunny.db deleted file mode 100644 index ba69319..0000000 Binary files a/Bunny.WebApi/Database/bunny.db and /dev/null differ diff --git a/Bunny.WebApi/Database/bunny.db-shm b/Bunny.WebApi/Database/bunny.db-shm deleted file mode 100644 index 7600918..0000000 Binary files a/Bunny.WebApi/Database/bunny.db-shm and /dev/null differ diff --git a/Bunny.WebApi/Database/bunny.db-wal b/Bunny.WebApi/Database/bunny.db-wal deleted file mode 100644 index 07ff647..0000000 Binary files a/Bunny.WebApi/Database/bunny.db-wal and /dev/null differ diff --git a/Bunny.WebApi/Program.cs b/Bunny.WebApi/Program.cs index 87d7101..827681d 100644 --- a/Bunny.WebApi/Program.cs +++ b/Bunny.WebApi/Program.cs @@ -1,4 +1,4 @@ -using Bunny.WebApi.Config; +using Bunny.WebApi.Configuration; using IGeekFan.AspNetCore.Knife4jUI; namespace Bunny.WebApi; @@ -13,7 +13,6 @@ public class Program // 基础配置 var baseConfig = new BaseConfig(builder); baseConfig.Initialize(); - var app = builder.Build(); if (app.Environment.IsDevelopment()) diff --git a/Bunny.WebApi/ReadMe.md b/Bunny.WebApi/ReadMe.md index 297b093..4e6e28a 100644 --- a/Bunny.WebApi/ReadMe.md +++ b/Bunny.WebApi/ReadMe.md @@ -62,3 +62,77 @@ service.AddCaptcha(options => }); } ``` + +## AutoFac配置 + +### 自动注入按照名称注入 + +**AutoFac配置详情** + +```csharp +using Autofac; +using Bunny.Common.Attribute; +using Microsoft.AspNetCore.Mvc; + +namespace Bunny.WebApi.Config; + +public static class AddAutofacConfig +{ + /// + /// AutoFac自动注入约定名称 + /// 接口以Service结尾注入到IOC中 + /// + /// + public static void BuildContainer(ContainerBuilder builder) + { + // 扫描所以前缀Bunny的命名空间 + var assemblies = AppDomain.CurrentDomain.GetAssemblies().Where(t => t.FullName!.StartsWith("Bunny")); + + // 遍历注入服务 + foreach (var assembly in assemblies) + { + var types = assembly.GetTypes(); + + // 注入Service + var serviceTypes = types.Where(t => t.GetCustomAttributes(typeof(ServiceAttribute), false).Length != 0); + foreach (var serviceType in serviceTypes) + { + var interfaces = serviceType.GetInterfaces(); + builder.RegisterType(serviceType).As(interfaces).InstancePerDependency(); + } + + // 注入数据库相关 + var mapperTypes = types.Where(t => t.GetCustomAttributes(typeof(MapperAttribute), false).Length != 0); + foreach (var mapperType in mapperTypes) + { + var interfaces = mapperType.GetInterfaces(); + builder.RegisterType(mapperType).As(interfaces).InstancePerDependency(); + } + + // 注入后台服务 + var componentTypes = + types.Where(t => t.GetCustomAttributes(typeof(ComponentAttribute), false).Length != 0); + foreach (var componentType in componentTypes) + builder.RegisterType(componentType).AsSelf().As().SingleInstance(); + } + + // 如果不在在 Controller 层写构造函数可以打开这个,自动完成注入 + var controllerBaseType = typeof(ControllerBase); + builder.RegisterAssemblyTypes(typeof(Program).Assembly) + .Where(t => controllerBaseType.IsAssignableFrom(t) && t != controllerBaseType) + .PropertiesAutowired(); //支持属性注入 + } +} +``` + +**主程序入口配置** + +```csharp +// 让控制器实例由容器创建 +builder.Services.Replace(ServiceDescriptor.Transient()); + +// 如果将Service放在 WebApi同级目录下,可以完成Controller自动注入,不需要写构造函数 +builder.Services.Replace(ServiceDescriptor.Transient()); +builder.Services.AddControllers().AddJsonOptions(options => + options.JsonSerializerOptions.Converters.Add(new JsonDateTimeConverter())); +``` \ No newline at end of file diff --git a/Bunny.WebApi/appsettings.json b/Bunny.WebApi/appsettings.json index 28b0840..4b23dd5 100644 --- a/Bunny.WebApi/appsettings.json +++ b/Bunny.WebApi/appsettings.json @@ -8,7 +8,7 @@ }, "AllowedHosts": "*", "DataBase": { - "DataBaseConnection": "Database/bunny.db", + "DataBaseConnection": "192.168.3.98;Initial Catalog=BunnyDemo;TrustServerCertificate=True;Persist Security Info=True;User ID=sa;Password=abc1234.", "TimeOut": 6 }, "JWT": { diff --git a/Bunny.WebApi/bunny.db b/Bunny.WebApi/bunny.db deleted file mode 100644 index 6bcda78..0000000 Binary files a/Bunny.WebApi/bunny.db and /dev/null differ