全流程跑通啦~~框架完成基本功能增删改查

This commit is contained in:
橙子
2023-01-15 17:32:27 +08:00
parent f1e314fa13
commit 1314cf1c19
25 changed files with 296 additions and 80 deletions

View File

@@ -11,5 +11,6 @@ namespace Yi.Framework.Application.Contracts.Student.Dtos
/// </summary> /// </summary>
public class StudentCreateInputVo public class StudentCreateInputVo
{ {
public string Name { get; set; }
} }
} }

View File

@@ -8,5 +8,6 @@ namespace Yi.Framework.Application.Contracts.Student.Dtos
{ {
public class StudentGetListInputVo public class StudentGetListInputVo
{ {
public string? Name { get; set; }
} }
} }

View File

@@ -10,5 +10,6 @@ namespace Yi.Framework.Application.Contracts.Student.Dtos
public class StudentGetListOutputDto : IEntityDto<long> public class StudentGetListOutputDto : IEntityDto<long>
{ {
public long Id { get; set; } public long Id { get; set; }
public string Name { get; set; }
} }
} }

View File

@@ -10,5 +10,6 @@ namespace Yi.Framework.Application.Contracts.Student.Dtos
public class StudentGetOutputDto : IEntityDto<long> public class StudentGetOutputDto : IEntityDto<long>
{ {
public long Id { get; set; } public long Id { get; set; }
public string Name { get; set; }
} }
} }

View File

@@ -8,5 +8,7 @@ namespace Yi.Framework.Application.Contracts.Student.Dtos
{ {
public class StudentUpdateInputVo public class StudentUpdateInputVo
{ {
public long Id { get; set; }
public string Name { get; set; }
} }
} }

View File

@@ -1,12 +1,23 @@
using System; using AutoMapper;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Yi.Framework.Application.Contracts.Student.Dtos;
using Yi.Framework.Domain.Student.Entities;
namespace Yi.Framework.Application.Student.MapperConfig namespace Yi.Framework.Application.Student.MapperConfig
{ {
internal class StudentProfile public class StudentProfile: Profile
{ {
public StudentProfile()
{
CreateMap<StudentGetListInputVo, StudentEntity>();
CreateMap<StudentCreateInputVo, StudentEntity>();
CreateMap<StudentUpdateInputVo, StudentEntity>();
CreateMap<StudentEntity, StudentGetListOutputDto>();
CreateMap<StudentEntity, StudentGetOutputDto>();
}
} }
} }

View File

@@ -9,7 +9,7 @@ namespace AspNetCore.Microsoft.AspNetCore.Builder
{ {
public static class CorsUseExtensions public static class CorsUseExtensions
{ {
public static void UseCorsService(this IApplicationBuilder app) public static void UseCorsServer(this IApplicationBuilder app)
{ {
app.UseCors("CorsPolicy"); app.UseCors("CorsPolicy");
} }

View File

@@ -22,7 +22,7 @@ namespace Yi.Framework.Autofac.Extensions
{ {
if (a.FullName is not null) if (a.FullName is not null)
{ {
profileList.AddRange(AssemblyHelper.GetClassByInterfaces(a.FullName, typeof(Profile))); profileList.AddRange(AssemblyHelper.GetClassByParentClass(a.FullName, typeof(Profile)));
} }
}); });

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Yi.Framework.Core.Sqlsugar.Const
{
public class SqlsugarConst
{
public const string = "开启读写分离后,读库连接不能为空";
public const string DbType配置为空 = "DbType配置为空必须选择一个数据库类型";
}
}

View File

@@ -0,0 +1,59 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Yi.Framework.Core.Sqlsugar.Options;
namespace Yi.Framework.Core.Sqlsugar.Extensions
{
public static class SqlsugarCodeFirstExtensions
{
public static void UseSqlsugarCodeFirstServer(this IApplicationBuilder app)
{
var db = app.ApplicationServices.GetRequiredService<ISqlSugarClient>();
var options = app.ApplicationServices.GetRequiredService<IOptions<DbConnOptions>>();
var assemblys = new List<Assembly>();
//全盘加载
if (options.Value.EntityAssembly is null)
{
assemblys.AddRange(AppDomain.CurrentDomain.GetAssemblies().ToList());
}
//按需加载
else
{
options.Value.EntityAssembly.ForEach(a =>
{
assemblys.Add(Assembly.Load(a));
});
}
foreach (var assembly in assemblys)
{
TableInvoer(db, assembly.GetTypes().ToList());
}
}
private static void TableInvoer(ISqlSugarClient _Db, List<Type> typeList)
{
_Db.DbMaintenance.CreateDatabase();
foreach (var t in typeList)
{
//扫描如果存在SugarTable特性 并且 不是分表模型直接codefirst
if (t.GetCustomAttributes(false).Any(a => a.GetType().Equals(typeof(SugarTable))
&& !t.GetCustomAttributes(false).Any(a => a.GetType().Equals(typeof(SplitTableAttribute)))))
{
_Db.CodeFirst.SetStringDefaultLength(200).InitTables(t);//这样一个表就能成功创建了
}
}
}
}
}

View File

@@ -10,6 +10,8 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Yi.Framework.Core.Configuration; using Yi.Framework.Core.Configuration;
using Yi.Framework.Core.Model; using Yi.Framework.Core.Model;
using Yi.Framework.Core.Sqlsugar.Const;
using Yi.Framework.Core.Sqlsugar.Options;
using DbType = SqlSugar.DbType; using DbType = SqlSugar.DbType;
namespace Yi.Framework.Core.Sqlsugar.Extensions namespace Yi.Framework.Core.Sqlsugar.Extensions
@@ -18,11 +20,24 @@ namespace Yi.Framework.Core.Sqlsugar.Extensions
{ {
public static void AddSqlsugarServer(this IServiceCollection services, Action<SqlSugarClient>? action = null) public static void AddSqlsugarServer(this IServiceCollection services, Action<SqlSugarClient>? action = null)
{ {
DbType dbType; var dbConnOptions = Appsettings.app<DbConnOptions>("DbConnOptions");
var slavaConFig = new List<SlaveConnectionConfig>();
if (Appsettings.appBool("MutiDB_Enabled")) if (dbConnOptions.DbType is null)
{ {
var readCon = Appsettings.app<List<string>>("DbConn", "ReadUrl"); throw new ArgumentException(SqlsugarConst.DbType配置为空);
}
var slavaConFig = new List<SlaveConnectionConfig>();
if (dbConnOptions.EnabledReadWrite)
{
if (dbConnOptions.ReadUrl is null)
{
throw new ArgumentException(SqlsugarConst.);
}
var readCon = dbConnOptions.ReadUrl;
readCon.ForEach(s => readCon.ForEach(s =>
{ {
@@ -31,19 +46,14 @@ namespace Yi.Framework.Core.Sqlsugar.Extensions
}); });
} }
switch (Appsettings.app("DbSelect"))
{
case "Mysql": dbType = DbType.MySql; break;
case "Sqlite": dbType = DbType.Sqlite; break;
case "Sqlserver": dbType = DbType.SqlServer; break;
case "Oracle": dbType = DbType.Oracle; break;
default: throw new Exception("DbSelect配置写的TM是个什么东西");
}
SqlSugarScope sqlSugar = new SqlSugarScope(new ConnectionConfig() SqlSugarScope sqlSugar = new SqlSugarScope(new ConnectionConfig()
{ {
//准备添加分表分库 //准备添加分表分库
DbType = dbType, DbType = dbConnOptions.DbType ?? DbType.Sqlite,
ConnectionString = Appsettings.app("DbConn", "WriteUrl"), ConnectionString = dbConnOptions.Url,
IsAutoCloseConnection = true, IsAutoCloseConnection = true,
MoreSettings = new ConnMoreSettings() MoreSettings = new ConnMoreSettings()
{ {
@@ -55,13 +65,6 @@ namespace Yi.Framework.Core.Sqlsugar.Extensions
{ {
EntityService = (c, p) => EntityService = (c, p) =>
{ {
//// int? decimal?这种 isnullable=true
//if (c.PropertyType.IsGenericType &&
//c.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
//{
// p.IsNullable = true;
//}
//高版C#写法 支持string?和string //高版C#写法 支持string?和string
if (new NullabilityInfoContext() if (new NullabilityInfoContext()
.Create(c).WriteState is NullabilityState.Nullable) .Create(c).WriteState is NullabilityState.Nullable)
@@ -73,6 +76,7 @@ namespace Yi.Framework.Core.Sqlsugar.Extensions
}, },
db => db =>
{ {
//扩展
if (action is not null) if (action is not null)
{ {
action(db); action(db);
@@ -80,32 +84,12 @@ namespace Yi.Framework.Core.Sqlsugar.Extensions
db.Aop.DataExecuting = (oldValue, entityInfo) => db.Aop.DataExecuting = (oldValue, entityInfo) =>
{ {
//var httpcontext = ServiceLocator.Instance.GetService<IHttpContextAccessor>().HttpContext;
switch (entityInfo.OperationType) switch (entityInfo.OperationType)
{ {
case DataFilterType.InsertByObject: case DataFilterType.InsertByObject:
if (entityInfo.PropertyName == "CreateUser")
{
//entityInfo.SetValue(new Guid(httpcontext.Request.Headers["Id"].ToString()));
}
if (entityInfo.PropertyName == "TenantId")
{
//entityInfo.SetValue(new Guid(httpcontext.Request.Headers["TenantId"].ToString()));
}
if (entityInfo.PropertyName == "CreateTime")
{
entityInfo.SetValue(DateTime.Now);
}
break; break;
case DataFilterType.UpdateByObject: case DataFilterType.UpdateByObject:
if (entityInfo.PropertyName == "ModifyTime")
{
entityInfo.SetValue(DateTime.Now);
}
if (entityInfo.PropertyName == "ModifyUser")
{
//entityInfo.SetValue(new Guid(httpcontext.Request.Headers["Id"].ToString()));
}
break; break;
} }
@@ -125,8 +109,6 @@ namespace Yi.Framework.Core.Sqlsugar.Extensions
sb.Append($"\r\n 完整SQL{UtilMethods.GetSqlString(DbType.MySql, s, p)}"); sb.Append($"\r\n 完整SQL{UtilMethods.GetSqlString(DbType.MySql, s, p)}");
_logger?.LogInformation(sb.ToString()); _logger?.LogInformation(sb.ToString());
} }
}; };
}); });

View File

@@ -0,0 +1,47 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Yi.Framework.Core.Sqlsugar.Options
{
public class DbConnOptions
{
/// <summary>
/// 连接字符串,必填
/// </summary>
public string? Url { get; set; }
/// <summary>
/// 数据库类型
/// </summary>
public DbType? DbType { get; set; }
/// <summary>
/// 开启种子数据
/// </summary>
public bool EnabledDbSeed = false;
/// <summary>
/// 开启读写分离
/// </summary>
public bool EnabledReadWrite = false;
/// <summary>
/// 开启codefirst
/// </summary>
public bool EnabledCodeFirst = false;
/// <summary>
/// 实体程序集
/// </summary>
public List<string>? EntityAssembly;
/// <summary>
/// 读写分离
/// </summary>
public List<string>? ReadUrl { get; set; }
}
}

View File

@@ -16,8 +16,8 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Options\" />
<Folder Include="Uow\" /> <Folder Include="Uow\" />
<Folder Include="CodeFirst\" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -2,8 +2,8 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using StartupModules; using StartupModules;
using Yi.Framework.Core.Configuration; using Yi.Framework.Core.Configuration;
using Yi.Framework.Core.Options;
using Yi.Framework.Core.Sqlsugar.Extensions; using Yi.Framework.Core.Sqlsugar.Extensions;
using Yi.Framework.Core.Sqlsugar.Options;
using Yi.Framework.Core.Sqlsugar.Repositories; using Yi.Framework.Core.Sqlsugar.Repositories;
using Yi.Framework.Ddd; using Yi.Framework.Ddd;
using Yi.Framework.Ddd.Repositories; using Yi.Framework.Ddd.Repositories;
@@ -14,13 +14,15 @@ namespace Yi.Framework.Core.Sqlsugar
{ {
public void Configure(IApplicationBuilder app, ConfigureMiddlewareContext context) public void Configure(IApplicationBuilder app, ConfigureMiddlewareContext context)
{ {
app.UseSqlsugarCodeFirstServer();
} }
public void ConfigureServices(IServiceCollection services, ConfigureServicesContext context) public void ConfigureServices(IServiceCollection services, ConfigureServicesContext context)
{ {
services.AddTransient(typeof(IRepository<>), typeof(SqlsugarRepository<>)); services.AddTransient(typeof(IRepository<>), typeof(SqlsugarRepository<>));
services.Configure<SqlConnOptions>(Appsettings.appConfiguration("DbConn")); services.Configure<DbConnOptions>(Appsettings.appConfiguration("DbConnOptions"));
services.AddSqlsugarServer(); services.AddSqlsugarServer();
} }
} }
} }

View File

@@ -41,6 +41,26 @@ namespace Yi.Framework.Core.Helper
).ToList(); ).ToList();
} }
public static List<Type> GetClassByParentClass(string assemblyFile, Type type)
{
Assembly assembly = Assembly.Load(assemblyFile);
List<Type> resList = new List<Type>();
List<Type> typeList = assembly.GetTypes().Where(m => m.IsClass).ToList();
foreach (var t in typeList)
{
var data = t.BaseType;
if (data == type)
{
resList.Add(t);
}
}
return resList;
}
public static List<Type> GetClassByInterfaces(string assemblyFile, Type type) public static List<Type> GetClassByInterfaces(string assemblyFile, Type type)
{ {
Assembly assembly = Assembly.Load(assemblyFile); Assembly assembly = Assembly.Load(assemblyFile);

View File

@@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Yi.Framework.Core.Helper
{
public static class ReflexHelper
{
#region
/// <summary>
/// 取对象属性值
/// </summary>
/// <param name="FieldName"></param>
/// <param name="obj"></param>
/// <returns></returns>
public static string GetModelValue(string FieldName, object obj)
{
try
{
Type Ts = obj.GetType();
object o = Ts.GetProperty(FieldName).GetValue(obj, null);
if (null == o)
return null;
string Value = Convert.ToString(o);
if (string.IsNullOrEmpty(Value))
return null;
return Value;
}
catch (Exception ex)
{
throw ex;
}
return null;
}
/// <summary>
/// 设置对象属性值
/// </summary>
/// <param name="FieldName"></param>
/// <param name="Value"></param>
/// <param name="obj"></param>
/// <returns></returns>
public static bool SetModelValue(string FieldName, object Value, object obj)
{
try
{
Type Ts = obj.GetType();
//object v = Convert.ChangeType(Value, Ts.GetProperty(FieldName).PropertyType);
Ts.GetProperty(FieldName).SetValue(obj, Value, null);
return true;
}
catch (Exception ex)
{
throw ex;
}
return false;
}
#endregion
}
}

View File

@@ -1,4 +1,5 @@
using System; using SqlSugar;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@@ -8,6 +9,8 @@ namespace Yi.Framework.Core.Helper
{ {
public static class SnowflakeHelper public static class SnowflakeHelper
{ {
public static long NextId { get => SnowFlakeSingle.Instance.NextId(); }
public static long Next() public static long Next()
{ {
SnowflakeTool snowflakeTool = new SnowflakeTool(1); SnowflakeTool snowflakeTool = new SnowflakeTool(1);

View File

@@ -1,14 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Yi.Framework.Core.Options
{
public class SqlConnOptions
{
public string WriteUrl { get; set; } = string.Empty;
public List<string>? ReadUrl { get; set; }
}
}

View File

@@ -8,6 +8,7 @@
<ItemGroup> <ItemGroup>
<Folder Include="Module\" /> <Folder Include="Module\" />
<Folder Include="Options\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -1,14 +1,16 @@
using AutoMapper; using AutoMapper;
using Microsoft.Extensions.DependencyInjection;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Yi.Framework.Core.Model;
namespace Yi.Framework.Ddd.Services namespace Yi.Framework.Ddd.Services
{ {
public abstract class ApplicationService public abstract class ApplicationService
{ {
public IMapper _mapper { get; set; } public IMapper _mapper { get => ServiceLocatorModel.Instance.GetRequiredService<IMapper>(); }
} }
} }

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Yi.Framework.Core.Helper;
using Yi.Framework.Ddd.Dtos; using Yi.Framework.Ddd.Dtos;
using Yi.Framework.Ddd.Entities; using Yi.Framework.Ddd.Entities;
using Yi.Framework.Ddd.Services.Abstract; using Yi.Framework.Ddd.Services.Abstract;
@@ -62,11 +63,15 @@ namespace Yi.Framework.Ddd.Services
//这里判断实体的T给id赋值 //这里判断实体的T给id赋值
//雪花id //雪花id
//if (entity is IEntity<long>) if (entity is IEntity<long> entityForlongId)
//{ {
// //使用反射暂时先使用sqlsuga的雪花id提供 if (entityForlongId.Id is default(long))
// entityWithLongId.Id = SqlSugar.SnowFlakeSingle.Instance.NextId(); {
//} //使用反射暂时先使用sqlsuga的雪花id提供
//ps: linshi
ReflexHelper.SetModelValue("Id", SnowflakeHelper.NextId, entity);
}
}
return Task.FromResult(entity); return Task.FromResult(entity);
@@ -86,6 +91,7 @@ namespace Yi.Framework.Ddd.Services
{ {
var entity = await MapToEntityAsync(input); var entity = await MapToEntityAsync(input);
//这里还可以设置租户
await _repository.InsertAsync(entity); await _repository.InsertAsync(entity);
return await MapToGetOutputDtoAsync(entity); return await MapToGetOutputDtoAsync(entity);

View File

@@ -1,8 +1,10 @@
using System; using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Yi.Framework.Core.Model;
using Yi.Framework.Ddd.Dtos; using Yi.Framework.Ddd.Dtos;
using Yi.Framework.Ddd.Entities; using Yi.Framework.Ddd.Entities;
using Yi.Framework.Ddd.Repositories; using Yi.Framework.Ddd.Repositories;
@@ -30,7 +32,10 @@ where TEntityDto : IEntityDto<TKey>
IReadOnlyAppService<TGetOutputDto, TGetListOutputDto, TKey, TGetListInput> IReadOnlyAppService<TGetOutputDto, TGetListOutputDto, TKey, TGetListInput>
where TEntity : class, IEntity where TEntity : class, IEntity
{ {
protected IRepository<TEntity> _repository { get; } /// <summary>
/// 先暂时用服务定位的方式,之后将更改为属性注入
/// </summary>
protected IRepository<TEntity> _repository { get => ServiceLocatorModel.Instance.GetRequiredService<IRepository<TEntity>>(); }
//Mapper //Mapper
protected virtual Task<TGetOutputDto> MapToGetOutputDtoAsync(TEntity entity) protected virtual Task<TGetOutputDto> MapToGetOutputDtoAsync(TEntity entity)

View File

@@ -28,6 +28,11 @@
<returns></returns> <returns></returns>
<exception cref="T:System.ArgumentNullException"></exception> <exception cref="T:System.ArgumentNullException"></exception>
</member> </member>
<member name="P:Yi.Framework.Ddd.Services.ReadOnlyAppService`5._repository">
<summary>
先暂时用服务定位的方式,之后将更改为属性注入
</summary>
</member>
<member name="M:Yi.Framework.Ddd.Services.ReadOnlyAppService`5.GetAsync(`3)"> <member name="M:Yi.Framework.Ddd.Services.ReadOnlyAppService`5.GetAsync(`3)">
<summary> <summary>
单查 单查

View File

@@ -10,13 +10,16 @@
//程序启动地址,*代表全部网口 //程序启动地址,*代表全部网口
"StartUrl": "http://*:19002", "StartUrl": "http://*:19002",
//数据库列表 //数据库类型列表
"DbList": [ "Sqlite", "Mysql", "Sqlserver", "Oracle" ], "DbList": [ "Sqlite", "Mysql", "Sqlserver", "Oracle" ],
//数据库类型选择
"DbSelect": "Sqlite", "DbConnOptions": {
//数据库连接地址,支持读写分离 "Url": "DataSource=yi-sqlsugar-dev.db",
"DbConn": { "DbType": "Sqlite",
"WriteUrl": "DataSource=yi-sqlsugar-dev.db", "EnabledDbSeed": false,
"EnabledReadWrite": false,
"EnabledCodeFirst": false,
"EntityAssembly": null,
"ReadUrl": [ "ReadUrl": [
"DataSource=[xxxx]", //sqlite "DataSource=[xxxx]", //sqlite
"server=[xxxx];port=3306;database=[xxxx];user id=[xxxx];password=[xxxx]", //mysql "server=[xxxx];port=3306;database=[xxxx];user id=[xxxx];password=[xxxx]", //mysql