feat(优化): 数据库连接优化;启动项目时如果不存在自动创建数据库;删除不必要内容;将数据库改为SqlServer

This commit is contained in:
bunny 2024-09-02 09:31:34 +08:00
commit f00cd37feb
52 changed files with 870 additions and 659 deletions

View File

@ -1,15 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
<data-source source="LOCAL" name="bunny" uuid="1a151f4f-7b33-40a5-b425-02b84edb60e6">
<data-source source="LOCAL" name="bunny" uuid="b6cf8a1e-027c-4a20-8eff-d18024c58281">
<driver-ref>sqlite.xerial</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
<jdbc-url>jdbc:sqlite:D:\MyFolder\Bunny\Bunny-cli\CSharp\CSharp-Single-EFCore\Bunny.WebApi\bunny.db</jdbc-url>
<jdbc-url>jdbc:sqlite:D:\Project\web\Bunny-Cli\template\CSharp\CSharp-Single-EFCore\Bunny.WebApi\Database\bunny.db</jdbc-url>
<jdbc-additional-properties>
<property name="com.intellij.clouds.kubernetes.db.enabled" value="false" />
</jdbc-additional-properties>
<working-dir>$ProjectFileDir$</working-dir>
<libraries>
<library>
<url>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</url>
</library>
<library>
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar</url>
</library>
</libraries>
</data-source>
</component>
</project>

View File

@ -57,11 +57,10 @@ public class AppSettings
}
public static T GetAppConfig<T>(string key, T? defaultValue = default)
public static T? GetAppConfig<T>(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))!;
;
}
/// <summary>
@ -71,7 +70,7 @@ public class AppSettings
/// <returns></returns>
public static string GetConfig(string key)
{
return Configuration[key];
return Configuration[key]!;
}
/// <summary>
@ -82,6 +81,6 @@ public class AppSettings
/// <returns>节点类型实例</returns>
public static T Get<T>(string key)
{
return Configuration.GetSection(key).Get<T>();
return Configuration.GetSection(key).Get<T>()!;
}
}

View File

@ -10,14 +10,14 @@
<PackageReference Include="Microsoft.AspNetCore" Version="2.2.0"/>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.6"/>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5"/>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.7">
<PrivateAssets>all</PrivateAssets>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.8">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.7"/>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.7">
<PrivateAssets>all</PrivateAssets>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.8"/>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.8">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Minio" Version="6.0.3"/>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3"/>

View File

@ -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<string>("DataBase:DataBaseConnection");
DbPath = dataBaseConnection;
}
public string DbPath { get; }
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
public DbSet<Product> Products { get; set; }
public DbSet<User> Users { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
options.UseSqlite($"Data Source={DbPath}");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// 添加过滤器
modelBuilder.Entity<BaseEntity>()
.HasQueryFilter(e => !e.IsDeleted);
// 默认值为false表示未删除
modelBuilder.Entity<BaseEntity>()
.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<int> SaveChangesAsync(CancellationToken cancellationToken = new())
{
SetSystemField();
return base.SaveChangesAsync(cancellationToken);
}
public override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess,
CancellationToken cancellationToken = new())
{
SetSystemField();
return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
}
/// <summary>
/// 系统字段赋值
/// </summary>
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();
}
}
}

View File

@ -3,33 +3,33 @@
public class BaseContext
{
// 使用Lazy初始化确保线程安全
public static readonly ThreadLocal<long?> UserId = new();
public static readonly ThreadLocal<string?> Token = new();
public static readonly ThreadLocal<long?>? UserId = null;
public static readonly ThreadLocal<string?>? 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;
}
}

View File

@ -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;
/// <summary>
/// EfCore 连接内容
/// dotnet tool install --global dotnet-ef
/// dotnet add package Microsoft.EntityFrameworkCore.Design
/// dotnet ef migrations add InitialCreate
/// dotnet ef database update
/// </summary>
public class EfCoreContext : DbContext
{
public EfCoreContext()
{
// var dataBaseConnection = AppSettings.GetAppConfig<string>("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<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
public DbSet<Product> Products { get; set; }
public DbSet<User> Users { get; set; }
/// <summary>
/// 配置数据库上下文选项,指定数据库连接字符串
/// </summary>
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
options.UseSqlServer(DbPath).AddInterceptors(new TransactionInterceptor());
}
/// <summary>
/// 在创建模型时为所有继承自BaseEntity的实体类型添加软删除查询过滤器
/// </summary>
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
if (typeof(BaseEntity).IsAssignableFrom(entityType.ClrType))
entityType.AddSoftDeleteQueryFilter();
base.OnModelCreating(modelBuilder);
}
/// <summary>
/// 重写SaveChanges方法在保存更改之前设置系统字段
/// </summary>
public override int SaveChanges()
{
SetSystemField();
return base.SaveChanges();
}
/// <summary>
/// 重写SaveChanges方法在保存更改之前设置系统字段
/// </summary>
public override int SaveChanges(bool acceptAllChangesOnSuccess)
{
SetSystemField();
return base.SaveChanges(acceptAllChangesOnSuccess);
}
/// <summary>
/// 异步保存更改,设置系统字段
/// </summary>
public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = new())
{
SetSystemField();
return base.SaveChangesAsync(cancellationToken);
}
/// <summary>
/// 异步保存更改,设置系统字段
/// </summary>
public override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess,
CancellationToken cancellationToken = new())
{
SetSystemField();
return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
}
/// <summary>
/// 系统字段赋值
/// </summary>
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;
}
}
}
}

View File

@ -2,7 +2,7 @@
using System.Text.Json.Serialization;
using Bunny.Dao.Model.Constant;
namespace Bunny.Common.Configuration;
namespace Bunny.Common.Context;
/// <summary>
/// 自定义Json转换器用于将DateTime类型转换为JSON格式

View File

@ -1,7 +1,7 @@
using Microsoft.AspNetCore.Builder;
using Minio;
namespace Bunny.Common.Connect;
namespace Bunny.Common.Context;
public static class MinioContext
{

View File

@ -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)

View File

@ -0,0 +1,36 @@
using System.Linq.Expressions;
using System.Reflection;
using Bunny.Dao.Entity.Base;
using Microsoft.EntityFrameworkCore.Metadata;
namespace Bunny.Common.Context;
/// <summary>
/// 软删除过滤器
/// </summary>
public static class SoftDeleteQueryExtension
{
/// <summary>
/// 软删除过滤器
/// </summary>
/// <param name="entityData"></param>
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!);
}
/// <summary>
/// 软删除
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <returns></returns>
private static LambdaExpression GetSoftDeleteFilter<TEntity>() where TEntity : BaseEntity
{
Expression<Func<TEntity, bool>> filter = x => !x.IsDeleted;
return filter;
}
}

View File

@ -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<string>.Error(HttpStatusCode.BadRequest, errorMessage);
var result =
Result<ModelStateDictionary>.Error(HttpStatusCode.BadRequest, actionContext.ModelState, errorMessage);
// 重新复写返回结果
actionContext.Result = new ObjectResult(result);

View File

@ -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<int> SavingChanges(DbContextEventData eventData, InterceptionResult<int> 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;
}
}

View File

@ -1,173 +0,0 @@
// <auto-generated />
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
{
/// <inheritdoc />
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<string>("Id")
.HasColumnType("TEXT");
b.Property<DateTime>("CreateTime")
.HasColumnType("TEXT");
b.Property<long>("CreateUserId")
.HasColumnType("INTEGER");
b.Property<DateTime>("UpdateTime")
.HasColumnType("TEXT");
b.Property<long>("UpdateUserId")
.HasColumnType("INTEGER");
b.Property<string>("Url")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Blogs");
});
modelBuilder.Entity("Bunny.Dao.Models.System.Post", b =>
{
b.Property<string>("Id")
.HasColumnType("TEXT");
b.Property<int>("BlogId")
.HasColumnType("INTEGER");
b.Property<string>("BlogId1")
.HasColumnType("TEXT");
b.Property<string>("Content")
.HasColumnType("TEXT");
b.Property<DateTime>("CreateTime")
.HasColumnType("TEXT");
b.Property<long>("CreateUserId")
.HasColumnType("INTEGER");
b.Property<int>("PostId")
.HasColumnType("INTEGER");
b.Property<string>("Title")
.HasColumnType("TEXT");
b.Property<DateTime>("UpdateTime")
.HasColumnType("TEXT");
b.Property<long>("UpdateUserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("BlogId1");
b.ToTable("Posts");
});
modelBuilder.Entity("Bunny.Dao.Models.System.Product", b =>
{
b.Property<string>("Id")
.HasColumnType("TEXT");
b.Property<DateTime>("CreateTime")
.HasColumnType("TEXT");
b.Property<long>("CreateUserId")
.HasColumnType("INTEGER");
b.Property<string>("CustomerId")
.HasColumnType("TEXT");
b.Property<string>("CustomerName")
.HasColumnType("TEXT");
b.Property<string>("PackageType")
.HasColumnType("TEXT");
b.Property<DateTime>("UpdateTime")
.HasColumnType("TEXT");
b.Property<long>("UpdateUserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.ToTable("Products");
});
modelBuilder.Entity("Bunny.Dao.Models.System.User", b =>
{
b.Property<string>("Id")
.HasColumnType("TEXT");
b.Property<string>("CompanyCode")
.HasColumnType("TEXT");
b.Property<DateTime>("CreateTime")
.HasColumnType("TEXT");
b.Property<long>("CreateUserId")
.HasColumnType("INTEGER");
b.Property<string>("DeptCode")
.HasColumnType("TEXT");
b.Property<string>("Email")
.HasColumnType("TEXT");
b.Property<string>("Password")
.HasColumnType("TEXT");
b.Property<string>("Phone")
.HasColumnType("TEXT");
b.Property<string>("QrCode")
.HasColumnType("TEXT");
b.Property<DateTime>("UpdateTime")
.HasColumnType("TEXT");
b.Property<long>("UpdateUserId")
.HasColumnType("INTEGER");
b.Property<string>("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
}
}
}

View File

@ -1,117 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Bunny.Common.Migrations
{
/// <inheritdoc />
public partial class InitialCreate : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Blogs",
columns: table => new
{
Id = table.Column<string>(type: "TEXT", nullable: false),
Url = table.Column<string>(type: "TEXT", nullable: false),
CreateTime = table.Column<DateTime>(type: "TEXT", nullable: false),
UpdateTime = table.Column<DateTime>(type: "TEXT", nullable: false),
CreateUserId = table.Column<long>(type: "INTEGER", nullable: false),
UpdateUserId = table.Column<long>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Blogs", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Products",
columns: table => new
{
Id = table.Column<string>(type: "TEXT", nullable: false),
CustomerId = table.Column<string>(type: "TEXT", nullable: true),
CustomerName = table.Column<string>(type: "TEXT", nullable: true),
PackageType = table.Column<string>(type: "TEXT", nullable: true),
CreateTime = table.Column<DateTime>(type: "TEXT", nullable: false),
UpdateTime = table.Column<DateTime>(type: "TEXT", nullable: false),
CreateUserId = table.Column<long>(type: "INTEGER", nullable: false),
UpdateUserId = table.Column<long>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Products", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Users",
columns: table => new
{
Id = table.Column<string>(type: "TEXT", nullable: false),
UserName = table.Column<string>(type: "TEXT", nullable: true),
Password = table.Column<string>(type: "TEXT", nullable: true),
Email = table.Column<string>(type: "TEXT", nullable: true),
Phone = table.Column<string>(type: "TEXT", nullable: true),
QrCode = table.Column<string>(type: "TEXT", nullable: true),
CompanyCode = table.Column<string>(type: "TEXT", nullable: true),
DeptCode = table.Column<string>(type: "TEXT", nullable: true),
CreateTime = table.Column<DateTime>(type: "TEXT", nullable: false),
UpdateTime = table.Column<DateTime>(type: "TEXT", nullable: false),
CreateUserId = table.Column<long>(type: "INTEGER", nullable: false),
UpdateUserId = table.Column<long>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Users", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Posts",
columns: table => new
{
Id = table.Column<string>(type: "TEXT", nullable: false),
PostId = table.Column<int>(type: "INTEGER", nullable: false),
Title = table.Column<string>(type: "TEXT", nullable: true),
Content = table.Column<string>(type: "TEXT", nullable: true),
BlogId = table.Column<int>(type: "INTEGER", nullable: false),
BlogId1 = table.Column<string>(type: "TEXT", nullable: true),
CreateTime = table.Column<DateTime>(type: "TEXT", nullable: false),
UpdateTime = table.Column<DateTime>(type: "TEXT", nullable: false),
CreateUserId = table.Column<long>(type: "INTEGER", nullable: false),
UpdateUserId = table.Column<long>(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");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Posts");
migrationBuilder.DropTable(
name: "Products");
migrationBuilder.DropTable(
name: "Users");
migrationBuilder.DropTable(
name: "Blogs");
}
}
}

View File

@ -0,0 +1,186 @@
// <auto-generated />
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
{
/// <inheritdoc />
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<string>("Id")
.HasColumnType("nvarchar(450)");
b.Property<DateTime>("CreateTime")
.HasColumnType("datetime2");
b.Property<long>("CreateUserId")
.HasColumnType("bigint");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<DateTime>("UpdateTime")
.HasColumnType("datetime2");
b.Property<long>("UpdateUserId")
.HasColumnType("bigint");
b.Property<string>("Url")
.IsRequired()
.HasColumnType("varchar(600)")
.HasColumnName("BlogUrl");
b.HasKey("Id");
b.ToTable("Blog");
});
modelBuilder.Entity("Bunny.Dao.Entity.System.Post", b =>
{
b.Property<string>("Id")
.HasColumnType("nvarchar(450)");
b.Property<string>("BlogId")
.HasColumnType("nvarchar(450)");
b.Property<string>("Content")
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("CreateTime")
.HasColumnType("datetime2");
b.Property<long>("CreateUserId")
.HasColumnType("bigint");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<string>("Title")
.HasMaxLength(600)
.HasColumnType("nvarchar(600)");
b.Property<DateTime>("UpdateTime")
.HasColumnType("datetime2");
b.Property<long>("UpdateUserId")
.HasColumnType("bigint");
b.HasKey("Id");
b.HasIndex("BlogId");
b.ToTable("Posts");
});
modelBuilder.Entity("Bunny.Dao.Entity.System.Product", b =>
{
b.Property<string>("Id")
.HasColumnType("nvarchar(450)");
b.Property<DateTime>("CreateTime")
.HasColumnType("datetime2");
b.Property<long>("CreateUserId")
.HasColumnType("bigint");
b.Property<string>("CustomerId")
.HasColumnType("nvarchar(max)");
b.Property<string>("CustomerName")
.HasColumnType("nvarchar(max)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<string>("PackageType")
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("UpdateTime")
.HasColumnType("datetime2");
b.Property<long>("UpdateUserId")
.HasColumnType("bigint");
b.HasKey("Id");
b.ToTable("Products");
});
modelBuilder.Entity("Bunny.Dao.Entity.System.User", b =>
{
b.Property<string>("Id")
.HasColumnType("nvarchar(450)");
b.Property<string>("CompanyCode")
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("CreateTime")
.HasColumnType("datetime2");
b.Property<long>("CreateUserId")
.HasColumnType("bigint");
b.Property<string>("DeptCode")
.HasColumnType("nvarchar(max)");
b.Property<string>("Email")
.HasColumnType("nvarchar(max)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<string>("Password")
.HasColumnType("nvarchar(max)");
b.Property<string>("Phone")
.HasColumnType("nvarchar(max)");
b.Property<string>("QrCode")
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("UpdateTime")
.HasColumnType("datetime2");
b.Property<long>("UpdateUserId")
.HasColumnType("bigint");
b.Property<string>("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
}
}
}

View File

@ -0,0 +1,119 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Bunny.Common.Migrations
{
/// <inheritdoc />
public partial class InitialCreate : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Blog",
columns: table => new
{
Id = table.Column<string>(type: "nvarchar(450)", nullable: false),
BlogUrl = table.Column<string>(type: "varchar(600)", nullable: false),
CreateTime = table.Column<DateTime>(type: "datetime2", nullable: false),
UpdateTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreateUserId = table.Column<long>(type: "bigint", nullable: false),
UpdateUserId = table.Column<long>(type: "bigint", nullable: false),
IsDeleted = table.Column<bool>(type: "bit", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Blog", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Products",
columns: table => new
{
Id = table.Column<string>(type: "nvarchar(450)", nullable: false),
CustomerId = table.Column<string>(type: "nvarchar(max)", nullable: true),
CustomerName = table.Column<string>(type: "nvarchar(max)", nullable: true),
PackageType = table.Column<string>(type: "nvarchar(max)", nullable: true),
CreateTime = table.Column<DateTime>(type: "datetime2", nullable: false),
UpdateTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreateUserId = table.Column<long>(type: "bigint", nullable: false),
UpdateUserId = table.Column<long>(type: "bigint", nullable: false),
IsDeleted = table.Column<bool>(type: "bit", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Products", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Users",
columns: table => new
{
Id = table.Column<string>(type: "nvarchar(450)", nullable: false),
UserName = table.Column<string>(type: "nvarchar(max)", nullable: true),
Password = table.Column<string>(type: "nvarchar(max)", nullable: true),
Email = table.Column<string>(type: "nvarchar(max)", nullable: true),
Phone = table.Column<string>(type: "nvarchar(max)", nullable: true),
QrCode = table.Column<string>(type: "nvarchar(max)", nullable: true),
CompanyCode = table.Column<string>(type: "nvarchar(max)", nullable: true),
DeptCode = table.Column<string>(type: "nvarchar(max)", nullable: true),
CreateTime = table.Column<DateTime>(type: "datetime2", nullable: false),
UpdateTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreateUserId = table.Column<long>(type: "bigint", nullable: false),
UpdateUserId = table.Column<long>(type: "bigint", nullable: false),
IsDeleted = table.Column<bool>(type: "bit", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Users", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Posts",
columns: table => new
{
Id = table.Column<string>(type: "nvarchar(450)", nullable: false),
Title = table.Column<string>(type: "nvarchar(600)", maxLength: 600, nullable: true),
Content = table.Column<string>(type: "nvarchar(max)", nullable: true),
BlogId = table.Column<string>(type: "nvarchar(450)", nullable: true),
CreateTime = table.Column<DateTime>(type: "datetime2", nullable: false),
UpdateTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreateUserId = table.Column<long>(type: "bigint", nullable: false),
UpdateUserId = table.Column<long>(type: "bigint", nullable: false),
IsDeleted = table.Column<bool>(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");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Posts");
migrationBuilder.DropTable(
name: "Products");
migrationBuilder.DropTable(
name: "Users");
migrationBuilder.DropTable(
name: "Blog");
}
}
}

View File

@ -1,8 +1,9 @@
// <auto-generated />
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<string>("Id")
.HasColumnType("TEXT");
.HasColumnType("nvarchar(450)");
b.Property<DateTime>("CreateTime")
.HasColumnType("TEXT");
.HasColumnType("datetime2");
b.Property<long>("CreateUserId")
.HasColumnType("INTEGER");
.HasColumnType("bigint");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<DateTime>("UpdateTime")
.HasColumnType("TEXT");
.HasColumnType("datetime2");
b.Property<long>("UpdateUserId")
.HasColumnType("INTEGER");
.HasColumnType("bigint");
b.Property<string>("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<string>("Id")
.HasColumnType("TEXT");
.HasColumnType("nvarchar(450)");
b.Property<int>("BlogId")
.HasColumnType("INTEGER");
b.Property<string>("BlogId1")
.HasColumnType("TEXT");
b.Property<string>("BlogId")
.HasColumnType("nvarchar(450)");
b.Property<string>("Content")
.HasColumnType("TEXT");
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("CreateTime")
.HasColumnType("TEXT");
.HasColumnType("datetime2");
b.Property<long>("CreateUserId")
.HasColumnType("INTEGER");
.HasColumnType("bigint");
b.Property<int>("PostId")
.HasColumnType("INTEGER");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<string>("Title")
.HasColumnType("TEXT");
.HasMaxLength(600)
.HasColumnType("nvarchar(600)");
b.Property<DateTime>("UpdateTime")
.HasColumnType("TEXT");
.HasColumnType("datetime2");
b.Property<long>("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<string>("Id")
.HasColumnType("TEXT");
.HasColumnType("nvarchar(450)");
b.Property<DateTime>("CreateTime")
.HasColumnType("TEXT");
.HasColumnType("datetime2");
b.Property<long>("CreateUserId")
.HasColumnType("INTEGER");
.HasColumnType("bigint");
b.Property<string>("CustomerId")
.HasColumnType("TEXT");
.HasColumnType("nvarchar(max)");
b.Property<string>("CustomerName")
.HasColumnType("TEXT");
.HasColumnType("nvarchar(max)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<string>("PackageType")
.HasColumnType("TEXT");
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("UpdateTime")
.HasColumnType("TEXT");
.HasColumnType("datetime2");
b.Property<long>("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<string>("Id")
.HasColumnType("TEXT");
.HasColumnType("nvarchar(450)");
b.Property<string>("CompanyCode")
.HasColumnType("TEXT");
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("CreateTime")
.HasColumnType("TEXT");
.HasColumnType("datetime2");
b.Property<long>("CreateUserId")
.HasColumnType("INTEGER");
.HasColumnType("bigint");
b.Property<string>("DeptCode")
.HasColumnType("TEXT");
.HasColumnType("nvarchar(max)");
b.Property<string>("Email")
.HasColumnType("TEXT");
.HasColumnType("nvarchar(max)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<string>("Password")
.HasColumnType("TEXT");
.HasColumnType("nvarchar(max)");
b.Property<string>("Phone")
.HasColumnType("TEXT");
.HasColumnType("nvarchar(max)");
b.Property<string>("QrCode")
.HasColumnType("TEXT");
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("UpdateTime")
.HasColumnType("TEXT");
.HasColumnType("datetime2");
b.Property<long>("UpdateUserId")
.HasColumnType("INTEGER");
.HasColumnType("bigint");
b.Property<string>("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");
});

View File

@ -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)

View File

@ -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;

View File

@ -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; }
}

View File

@ -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; }
}

View File

@ -8,7 +8,7 @@ public abstract class EmailSendEntity
/// <summary>
/// SMTP 服务器
/// </summary>
public string SmtpService { get; set; }
public string? SmtpService { get; set; }
/// <summary>
/// SMTP 服务器端口号
@ -18,32 +18,32 @@ public abstract class EmailSendEntity
/// <summary>
/// 发送者邮件
/// </summary>
public string SendEmail { get; set; }
public string? SendEmail { get; set; }
/// <summary>
/// 发送者密码
/// </summary>
public string SendEmailPassword { get; set; }
public string? SendEmailPassword { get; set; }
/// <summary>
/// 接受这邮件
/// </summary>
public string ReceiverEmail { get; set; }
public string? ReceiverEmail { get; set; }
/// <summary>
/// 发送邮件的主题
/// </summary>
public string Subject { get; set; }
public string? Subject { get; set; }
/// <summary>
/// 发送邮件的内容
/// </summary>
public string Body { get; set; }
public string? Body { get; set; }
/// <summary>
/// 设置抄送
/// </summary>
public string? CC { get; set; }
public string? Cc { get; set; }
/// <summary>
/// 是否密送

View File

@ -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; }
}

View File

@ -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; }
}

View File

@ -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 = "点赞内容不存在";

View File

@ -168,7 +168,7 @@ public class Result<T>(HttpStatusCode code, T? data, string? message)
/// <param name="message">消息内容</param>
/// <param name="data">数据内容分</param>
/// <returns>返回的数据内容</returns>
public static Result<T> Error(string message, T data)
public static Result<T> Error(T data, string message)
{
return new Result<T>(HttpStatusCode.InternalServerError, data, message);
}

View File

@ -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内容
/// </summary>
/// <param name="dto"></param>
void UpdateBlog(Blog dto);
void UpdateBlog(BlogUpdateDto dto);
/// <summary>
/// 删除BLog

View File

@ -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; }
/// <summary>
/// 添加Blog
@ -20,8 +18,8 @@ public class BlogService : IBlogService
/// <exception cref="NotImplementedException"></exception>
public void AddBlog(Blog dto)
{
_dbContext.Add(dto);
_dbContext.SaveChanges();
DbContext.Add(dto);
DbContext.SaveChanges();
}
/// <summary>
@ -30,17 +28,20 @@ public class BlogService : IBlogService
/// <returns></returns>
public List<Blog> QueryBlog()
{
return _dbContext.Blogs.ToList();
return DbContext.Blogs.ToList();
}
/// <summary>
/// 更新Blog内容
/// </summary>
/// <param name="dto"></param>
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();
}
/// <summary>
@ -49,9 +50,9 @@ public class BlogService : IBlogService
/// <param name="id"></param>
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();
}
/// <summary>
@ -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<Blog>();
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();
}
/// <summary>
@ -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<Blog>();
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
/// <param name="limit"></param>
public PageResult<Blog> 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);

View File

@ -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();
}
/// <summary>
@ -49,8 +44,8 @@ public class JobService : IJobService
var jobDetail = JobBuilder.Create<SimpleJob>()
.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))
// 设置工作时间在每周的星期几

View File

@ -1,5 +1,5 @@
using Bunny.Common;
using Bunny.Common.Connect;
using Bunny.Common.Context;
using Microsoft.AspNetCore.Http;
using Minio;
using Minio.DataModel;

View File

@ -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!;
/// <summary>
@ -60,7 +60,7 @@ public class RedisOptionService : IRedisOptionService
{
var post = new Post
{
PostId = 1,
Id = Guid.NewGuid(),
Title = "存入JSON内容",
Content = "正在存入JSON内容"
};

View File

@ -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 =>

View File

@ -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);
}
}

View File

@ -27,6 +27,8 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Autofac" Version="8.0.0"/>
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="9.0.0"/>
<PackageReference Include="IGeekFan.AspNetCore.Knife4jUI" Version="0.0.16"/>
<PackageReference Include="log4net" Version="2.0.17"/>
<PackageReference Include="Microsoft.Extensions.Logging.Log4Net.AspNetCore" Version="8.0.0"/>

View File

@ -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<EfCoreContext>();
// 注入Service服务
builder.RegisterType<BaseService>().As<IBaseService>();
builder.RegisterType<BlogService>().As<IBlogService>();
builder.RegisterType<RedisOptionService>().As<IRedisOptionService>();
builder.RegisterType<JobService>().As<IJobService>();
builder.RegisterType<MinioService>().As<IMinioService>();
}
}

View File

@ -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)
{
@ -15,21 +18,22 @@ public class BaseConfig(WebApplicationBuilder builder)
// 配置跨域
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<ContainerBuilder>(AddAutofacConfig.BuildContainer);
// 让控制器实例由容器创建
builder.Services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());
// 添加定时任务
builder.AddApplicationBackendServices();
// 设置过滤器

View File

@ -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
{

View File

@ -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<EfCoreContext>();
// 注入Service服务
builder.Services.AddScoped<IBaseService, BaseService>();
builder.Services.AddScoped<IBlogService, BlogService>();
builder.Services.AddScoped<IRedisOptionService, RedisOptionService>();
builder.Services.AddScoped<IJobService, JobService>();
builder.Services.AddScoped<IMinioService, MinioService>();
}
/// <summary>
/// 注入后台服务相关
/// 用于添加所以Job服务之后在BaseConfig中进行调用

View File

@ -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;
/// <summary>
/// BLog相关接口
/// </summary>
[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; }
/// <summary>
/// 添加Blog
@ -26,7 +23,7 @@ public class BlogController : ControllerBase
[HttpPost]
public Result<object> AddBlog(Blog dto)
{
_blogService.AddBlog(dto);
BlogService.AddBlog(dto);
return Result<object>.Success();
}
@ -37,7 +34,7 @@ public class BlogController : ControllerBase
[HttpGet]
public Result<List<Blog>> QueryBlog()
{
var vo = _blogService.QueryBlog();
var vo = BlogService.QueryBlog();
return Result<List<Blog>>.Success(vo);
}
@ -47,9 +44,9 @@ public class BlogController : ControllerBase
/// <param name="dto"></param>
/// <returns></returns>
[HttpPost]
public Result<object> UpdateBlog(Blog dto)
public Result<object> UpdateBlog(BlogUpdateDto dto)
{
_blogService.UpdateBlog(dto);
BlogService.UpdateBlog(dto);
return Result<object>.Success();
}
@ -60,7 +57,7 @@ public class BlogController : ControllerBase
[HttpDelete]
public Result<string> DeleteBlog(string id)
{
_blogService.DeleteBlog(id);
BlogService.DeleteBlog(id);
return Result<string>.Success();
}
@ -71,7 +68,7 @@ public class BlogController : ControllerBase
[HttpPost]
public Result<string> AddBatchBlogs(string url)
{
_blogService.AddBatchBlogs(url);
BlogService.AddBatchBlogs(url);
return Result<string>.Success();
}
@ -82,7 +79,7 @@ public class BlogController : ControllerBase
[HttpGet]
public Result<string> DeleteBatchBlogs()
{
_blogService.DeleteBatchBlogs();
BlogService.DeleteBatchBlogs();
return Result<string>.Success();
}
@ -93,7 +90,7 @@ public class BlogController : ControllerBase
[HttpGet]
public Result<string> UseTransaction()
{
_blogService.UseTransaction();
BlogService.UseTransaction();
return Result<string>.Success();
}
@ -104,7 +101,7 @@ public class BlogController : ControllerBase
[HttpPost]
public Result<PageResult<Blog>> QueryPage(int page = 1, int limit = 10)
{
var vo = _blogService.QueryPage(page, limit);
var vo = BlogService.QueryPage(page, limit);
return Result<PageResult<Blog>>.Success(vo);
}

View File

@ -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;
/// <summary>
/// 验证码测试
/// </summary>
[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; }
/// <summary>
/// 测试测试验证码生成
/// </summary>
@ -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<string> CheckCode(string id, string code)
{
// 校验用户输入的验证码是否=正确
var validate = _captcha.Validate(id, code);
return validate ? Result<string>.Success() : Result<string>.Error(ErrorConstant.ValidateCodeError);
var validate = Captcha.Validate(id, code);
return validate
? Result<string>.Success()
: Result<string>.Error(null!, ErrorConstant.ValidateCodeError);
}
}

View File

@ -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;
/// <summary>
/// Quartz 示例相关
/// </summary>
[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; }
/// <summary>
/// 1. 开启一个简单的工作
/// </summary>
@ -17,7 +20,7 @@ public class JobInitController(IJobService jobService) : ControllerBase
[HttpPost]
public Result<string> StartSimpleJob()
{
jobService.StartSimpleJob();
JobService.StartSimpleJob();
return Result<string>.Success("将名称生成放在jobDetail中可以再运行时获取到");
}
@ -28,7 +31,7 @@ public class JobInitController(IJobService jobService) : ControllerBase
[HttpPost]
public Result<string> PutJobDetail4Trigger()
{
jobService.PutJobDetail4Trigger();
JobService.PutJobDetail4Trigger();
return Result<string>.Success("将jobDetail中的一些信息放在触发器中简化写法");
}
@ -39,7 +42,7 @@ public class JobInitController(IJobService jobService) : ControllerBase
[HttpHead]
public Result<string> SetJobWithDaily()
{
jobService.SetJobWithDaily();
JobService.SetJobWithDaily();
return Result<string>.Success();
}
}

View File

@ -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; }
/// <summary>
/// 查询所有的桶
/// </summary>
@ -17,7 +20,7 @@ public class MinioController(IMinioService minioService) : ControllerBase
[HttpGet]
public Result<ListAllMyBucketsResult> GetAllMyBuckets()
{
var listAllMyBucketsResult = minioService.GetAllMyBuckets();
var listAllMyBucketsResult = MinioService.GetAllMyBuckets();
return Result<ListAllMyBucketsResult>.Success(listAllMyBucketsResult);
}
@ -29,7 +32,7 @@ public class MinioController(IMinioService minioService) : ControllerBase
[HttpPost]
public Result<string> SaveMinioFile(IFormFile? file, string filepath = "test")
{
minioService.SaveMinioFile(file, filepath);
MinioService.SaveMinioFile(file, filepath);
return Result<string>.Success("上传成功");
}
@ -42,7 +45,7 @@ public class MinioController(IMinioService minioService) : ControllerBase
[HttpGet]
public Result<ObjectStat> GetObjectStat(string filename, string bucketName = "csharp-test")
{
var vo = minioService.GetObjectStat(filename, bucketName);
var vo = MinioService.GetObjectStat(filename, bucketName);
return Result<ObjectStat>.Success(vo);
}
@ -55,7 +58,7 @@ public class MinioController(IMinioService minioService) : ControllerBase
[HttpGet]
public Result<string> GetObjectPath(string filename, string bucketName = "csharp-test")
{
var vo = minioService.GetObjectPath(filename, bucketName);
var vo = MinioService.GetObjectPath(filename, bucketName);
return Result<string>.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<IAsyncEnumerable<Item>> ListObject(string? filepath, string bucketName = "csharp-test")
{
var vo = minioService.ListObject(filepath, bucketName);
var vo = MinioService.ListObject(filepath, bucketName);
return Result<IAsyncEnumerable<Item>>.Success(vo);
}
}

View File

@ -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;
/// <summary>
/// 操作Redis相关内容
/// </summary>
[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; }
/// <summary>
/// 添加Redis中一个值
@ -26,7 +22,7 @@ public class RedisOptionController : ControllerBase
[HttpPost]
public Result<string> AddStringValue(string key, string value)
{
_redisOptionService.AddStringValue(key, value);
RedisOptionService.AddStringValue(key, value);
return Result<string>.Success();
}
@ -37,7 +33,7 @@ public class RedisOptionController : ControllerBase
[HttpPost]
public Result<string> QueryStringKey(string key)
{
var queryStringKey = _redisOptionService.QueryStringKey(key);
var queryStringKey = RedisOptionService.QueryStringKey(key);
return Result<string>.Success(queryStringKey);
}
@ -50,7 +46,7 @@ public class RedisOptionController : ControllerBase
[HttpPost]
public Result<string> AddTimeRedisKey(string key, string value)
{
_redisOptionService.AddTimeRedisKey(key, value);
RedisOptionService.AddTimeRedisKey(key, value);
return Result<string>.Success(value);
}
@ -63,7 +59,7 @@ public class RedisOptionController : ControllerBase
[HttpPost]
public Result<string> AddTimeRedisKeyTtl(string key, string value)
{
_redisOptionService.AddTimeRedisKeyTtl(key, value);
RedisOptionService.AddTimeRedisKeyTtl(key, value);
return Result<string>.Success(value);
}
@ -74,7 +70,7 @@ public class RedisOptionController : ControllerBase
[HttpGet]
public Result<string> AddJson()
{
var json = _redisOptionService.AddJson();
var json = RedisOptionService.AddJson();
return Result<string>.Success(json);
}
@ -86,7 +82,7 @@ public class RedisOptionController : ControllerBase
[HttpDelete]
public Result<string> DeleteKey(string key)
{
_redisOptionService.DeleteKey(key);
RedisOptionService.DeleteKey(key);
return Result<string>.Success();
}
@ -97,7 +93,7 @@ public class RedisOptionController : ControllerBase
[HttpPost]
public Result<string> SetRedisCreateTransaction(string key, string value)
{
var redisCreateTransaction = _redisOptionService.SetRedisCreateTransaction(key, value);
var redisCreateTransaction = RedisOptionService.SetRedisCreateTransaction(key, value);
return Result<string>.Success(redisCreateTransaction);
}
@ -108,7 +104,7 @@ public class RedisOptionController : ControllerBase
[HttpPost]
public Result<string> AddHashWithRedis(string key, double keyExpire = 6.0)
{
_redisOptionService.AddHashWithRedis(key, keyExpire);
RedisOptionService.AddHashWithRedis(key, keyExpire);
return Result<string>.Success();
}
}

View File

@ -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;
/// 测试请求模板
/// </summary>
[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; }
/// <summary>
/// 测试走缓存
@ -36,7 +32,7 @@ public class TemplateController : ControllerBase
[HttpGet("TestInject")]
public Result<string> TestInject()
{
var testIndex = _baseService.TestIndex();
var testIndex = BaseService.TestIndex();
return Result<string>.Success(testIndex);
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -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())

View File

@ -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
{
/// <summary>
/// AutoFac自动注入约定名称
/// 接口以Service结尾注入到IOC中
/// </summary>
/// <param name="builder"></param>
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<IHostedService>().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<IControllerActivator, ServiceBasedControllerActivator>());
// 如果将Service放在 WebApi同级目录下可以完成Controller自动注入不需要写构造函数
builder.Services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());
builder.Services.AddControllers().AddJsonOptions(options =>
options.JsonSerializerOptions.Converters.Add(new JsonDateTimeConverter()));
```

View File

@ -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": {

Binary file not shown.