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

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>
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 string? Name { get; set; }
}
}

View File

@@ -10,5 +10,6 @@ namespace Yi.Framework.Application.Contracts.Student.Dtos
public class StudentGetListOutputDto : IEntityDto<long>
{
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 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 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.Linq;
using System.Text;
using System.Threading.Tasks;
using Yi.Framework.Application.Contracts.Student.Dtos;
using Yi.Framework.Domain.Student.Entities;
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 void UseCorsService(this IApplicationBuilder app)
public static void UseCorsServer(this IApplicationBuilder app)
{
app.UseCors("CorsPolicy");
}

View File

@@ -22,7 +22,7 @@ namespace Yi.Framework.Autofac.Extensions
{
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 Yi.Framework.Core.Configuration;
using Yi.Framework.Core.Model;
using Yi.Framework.Core.Sqlsugar.Const;
using Yi.Framework.Core.Sqlsugar.Options;
using DbType = SqlSugar.DbType;
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)
{
DbType dbType;
var slavaConFig = new List<SlaveConnectionConfig>();
if (Appsettings.appBool("MutiDB_Enabled"))
var dbConnOptions = Appsettings.app<DbConnOptions>("DbConnOptions");
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 =>
{
@@ -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()
{
//准备添加分表分库
DbType = dbType,
ConnectionString = Appsettings.app("DbConn", "WriteUrl"),
DbType = dbConnOptions.DbType ?? DbType.Sqlite,
ConnectionString = dbConnOptions.Url,
IsAutoCloseConnection = true,
MoreSettings = new ConnMoreSettings()
{
@@ -55,13 +65,6 @@ namespace Yi.Framework.Core.Sqlsugar.Extensions
{
EntityService = (c, p) =>
{
//// int? decimal?这种 isnullable=true
//if (c.PropertyType.IsGenericType &&
//c.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
//{
// p.IsNullable = true;
//}
//高版C#写法 支持string?和string
if (new NullabilityInfoContext()
.Create(c).WriteState is NullabilityState.Nullable)
@@ -73,6 +76,7 @@ namespace Yi.Framework.Core.Sqlsugar.Extensions
},
db =>
{
//扩展
if (action is not null)
{
action(db);
@@ -80,32 +84,12 @@ namespace Yi.Framework.Core.Sqlsugar.Extensions
db.Aop.DataExecuting = (oldValue, entityInfo) =>
{
//var httpcontext = ServiceLocator.Instance.GetService<IHttpContextAccessor>().HttpContext;
switch (entityInfo.OperationType)
{
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;
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;
}
@@ -125,8 +109,6 @@ namespace Yi.Framework.Core.Sqlsugar.Extensions
sb.Append($"\r\n 完整SQL{UtilMethods.GetSqlString(DbType.MySql, s, p)}");
_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>
<Folder Include="Options\" />
<Folder Include="Uow\" />
<Folder Include="CodeFirst\" />
</ItemGroup>
</Project>

View File

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

View File

@@ -41,6 +41,26 @@ namespace Yi.Framework.Core.Helper
).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)
{
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.Linq;
using System.Text;
@@ -8,6 +9,8 @@ namespace Yi.Framework.Core.Helper
{
public static class SnowflakeHelper
{
public static long NextId { get => SnowFlakeSingle.Instance.NextId(); }
public static long Next()
{
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>
<Folder Include="Module\" />
<Folder Include="Options\" />
</ItemGroup>
<ItemGroup>

View File

@@ -1,14 +1,16 @@
using AutoMapper;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Yi.Framework.Core.Model;
namespace Yi.Framework.Ddd.Services
{
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.Text;
using System.Threading.Tasks;
using Yi.Framework.Core.Helper;
using Yi.Framework.Ddd.Dtos;
using Yi.Framework.Ddd.Entities;
using Yi.Framework.Ddd.Services.Abstract;
@@ -62,11 +63,15 @@ namespace Yi.Framework.Ddd.Services
//这里判断实体的T给id赋值
//雪花id
//if (entity is IEntity<long>)
//{
// //使用反射暂时先使用sqlsuga的雪花id提供
// entityWithLongId.Id = SqlSugar.SnowFlakeSingle.Instance.NextId();
//}
if (entity is IEntity<long> entityForlongId)
{
if (entityForlongId.Id is default(long))
{
//使用反射暂时先使用sqlsuga的雪花id提供
//ps: linshi
ReflexHelper.SetModelValue("Id", SnowflakeHelper.NextId, entity);
}
}
return Task.FromResult(entity);
@@ -86,6 +91,7 @@ namespace Yi.Framework.Ddd.Services
{
var entity = await MapToEntityAsync(input);
//这里还可以设置租户
await _repository.InsertAsync(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.Linq;
using System.Text;
using System.Threading.Tasks;
using Yi.Framework.Core.Model;
using Yi.Framework.Ddd.Dtos;
using Yi.Framework.Ddd.Entities;
using Yi.Framework.Ddd.Repositories;
@@ -30,7 +32,10 @@ where TEntityDto : IEntityDto<TKey>
IReadOnlyAppService<TGetOutputDto, TGetListOutputDto, TKey, TGetListInput>
where TEntity : class, IEntity
{
protected IRepository<TEntity> _repository { get; }
/// <summary>
/// 先暂时用服务定位的方式,之后将更改为属性注入
/// </summary>
protected IRepository<TEntity> _repository { get => ServiceLocatorModel.Instance.GetRequiredService<IRepository<TEntity>>(); }
//Mapper
protected virtual Task<TGetOutputDto> MapToGetOutputDtoAsync(TEntity entity)

View File

@@ -28,6 +28,11 @@
<returns></returns>
<exception cref="T:System.ArgumentNullException"></exception>
</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)">
<summary>
单查

View File

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