mirror of
https://gitee.com/dotnetchina/OpenAuth.Net.git
synced 2025-07-15 14:04:41 +08:00
feat: #I3OHS6 新增动态API功能
This commit is contained in:
parent
e7d4155b6d
commit
875b1d1c21
@ -1,18 +1,18 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Collections.Generic;
|
||||||
using Infrastructure;
|
using Infrastructure;
|
||||||
using OpenAuth.App.Interface;
|
using OpenAuth.App.Interface;
|
||||||
using OpenAuth.App.Response;
|
using OpenAuth.App.Response;
|
||||||
using OpenAuth.Repository.Core;
|
|
||||||
using SqlSugar;
|
using SqlSugar;
|
||||||
|
using OpenAuth.App.Request;
|
||||||
|
|
||||||
namespace OpenAuth.App
|
namespace OpenAuth.App
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 动态API应用层
|
/// 动态API应用层
|
||||||
/// 用于处理任意实体的CRUD操作
|
/// 用于直接操作数据库表,不依赖实体
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class DynamicApiApp
|
public class DynamicApiApp
|
||||||
{
|
{
|
||||||
@ -26,45 +26,39 @@ namespace OpenAuth.App
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取实体列表
|
/// 获取表数据列表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="entityName">实体名称,例如:ExternalDataSource</param>
|
/// <param name="req">查询参数</param>
|
||||||
/// <param name="page">页码</param>
|
|
||||||
/// <param name="limit">每页记录数</param>
|
|
||||||
/// <param name="key">搜索关键字</param>
|
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<TableData> GetList(string entityName, int page = 1, int limit = 10, string key = "")
|
public async Task<TableData> GetList(QueryDynamicListReq req)
|
||||||
{
|
{
|
||||||
var result = new TableData();
|
var result = new TableData();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 获取实体类型
|
// 验证表名是否存在
|
||||||
var entityType = GetEntityType(entityName);
|
if (!TableExists(req.TableName))
|
||||||
if (entityType == null)
|
|
||||||
{
|
{
|
||||||
result.code = 500;
|
result.code = 500;
|
||||||
result.msg = $"未找到实体:{entityName}";
|
result.msg = $"表不存在:{req.TableName}";
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建动态查询
|
// 创建动态查询
|
||||||
dynamic queryable = _client.GetType().GetMethod("Queryable", new Type[] { })
|
var queryable = _client.Queryable<dynamic>().AS(req.TableName);
|
||||||
.MakeGenericMethod(entityType)
|
|
||||||
.Invoke(_client, null);
|
// 获取表结构
|
||||||
|
var columns = GetTableColumns(req.TableName);
|
||||||
|
|
||||||
// 如果有搜索关键字,尝试在常见字段中搜索
|
// 如果有搜索关键字,尝试在常见字段中搜索
|
||||||
if (!string.IsNullOrEmpty(key))
|
if (!string.IsNullOrEmpty(req.key))
|
||||||
{
|
{
|
||||||
// 获取实体的所有属性
|
//todo: 尝试在Name、Title等常见字段中搜索
|
||||||
var properties = entityType.GetProperties();
|
var nameColumn = columns.FirstOrDefault(c =>
|
||||||
|
c.DbColumnName.Equals("Name", StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
// 尝试在Name、Title等常见字段中搜索
|
if (nameColumn != null)
|
||||||
var nameProperty = properties.FirstOrDefault(p =>
|
|
||||||
p.Name.Equals("Name", StringComparison.OrdinalIgnoreCase));
|
|
||||||
|
|
||||||
if (nameProperty != null)
|
|
||||||
{
|
{
|
||||||
queryable = queryable.Where($"{nameProperty.Name} like @key", new { key = $"%{key}%" });
|
queryable = queryable.Where($"{nameColumn.DbColumnName} like @key", new { key = $"%{req.key}%" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,9 +66,10 @@ namespace OpenAuth.App
|
|||||||
var total = await queryable.CountAsync();
|
var total = await queryable.CountAsync();
|
||||||
|
|
||||||
// 分页查询
|
// 分页查询
|
||||||
var list = await queryable.OrderBy("CreateTime DESC")
|
var list = await queryable
|
||||||
.Skip((page - 1) * limit)
|
.OrderBy($"{ columns[0].DbColumnName } DESC")
|
||||||
.Take(limit)
|
.Skip((req.page - 1) * req.limit)
|
||||||
|
.Take(req.limit)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
result.data = list;
|
result.data = list;
|
||||||
@ -90,31 +85,36 @@ namespace OpenAuth.App
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取实体详情
|
/// 获取表数据详情
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="entityName">实体名称,例如:ExternalDataSource</param>
|
/// <param name="tableName">表名称</param>
|
||||||
/// <param name="id">实体ID</param>
|
/// <param name="id">记录ID</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Response<object> Get(string entityName, string id)
|
public async Task<Response<object>> Get(QueryDynamicEntityReq req)
|
||||||
{
|
{
|
||||||
var result = new Response<object>();
|
var result = new Response<object>();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 获取实体类型
|
// 验证表名是否存在
|
||||||
var entityType = GetEntityType(entityName);
|
if (!TableExists(req.TableName))
|
||||||
if (entityType == null)
|
|
||||||
{
|
{
|
||||||
result.Code = 500;
|
result.Code = 500;
|
||||||
result.Message = $"未找到实体:{entityName}";
|
result.Message = $"表不存在:{req.TableName}";
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取实体
|
// 获取数据
|
||||||
dynamic queryable = _client.GetType().GetMethod("Queryable", new Type[] { })
|
var entity = await _client.Queryable<dynamic>()
|
||||||
.MakeGenericMethod(entityType)
|
.AS(req.TableName)
|
||||||
.Invoke(_client, null);
|
.Where("Id = @id", new { id = req.Id })
|
||||||
|
.FirstAsync();
|
||||||
|
|
||||||
var entity = queryable.Where("Id = @id", new { id }).First();
|
if (entity == null)
|
||||||
|
{
|
||||||
|
result.Code = 500;
|
||||||
|
result.Message = "未找到记录";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
result.Result = entity;
|
result.Result = entity;
|
||||||
}
|
}
|
||||||
@ -128,55 +128,63 @@ namespace OpenAuth.App
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 添加实体
|
/// 添加表数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="entityName">实体名称,例如:ExternalDataSource</param>
|
/// <param name="tableName">表名称</param>
|
||||||
/// <param name="obj">实体对象</param>
|
/// <param name="obj">数据对象
|
||||||
|
/// <para>如果数据里面没有Id,自动会添加ID</para>
|
||||||
|
/// </param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Infrastructure.Response Add(string entityName, object obj)
|
public async Task<Response<object>> Add(AddOrUpdateDynamicEntityReq req)
|
||||||
{
|
{
|
||||||
var result = new Infrastructure.Response();
|
var result = new Response<object>();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 获取实体类型
|
// 验证表名是否存在
|
||||||
var entityType = GetEntityType(entityName);
|
if (!TableExists(req.TableName))
|
||||||
if (entityType == null)
|
|
||||||
{
|
{
|
||||||
result.Code = 500;
|
result.Code = 500;
|
||||||
result.Message = $"未找到实体:{entityName}";
|
result.Message = $"表不存在:{req.TableName}";
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 将传入的对象转换为实体类型
|
// 将对象转换为字典
|
||||||
var entity = obj.MapTo(entityType);
|
var dict = req.Obj.ToDictionary();
|
||||||
|
|
||||||
// 设置创建信息
|
// 设置ID
|
||||||
var idProperty = entityType.GetProperty("Id");
|
if (!dict.ContainsKey("Id"))
|
||||||
if (idProperty != null && idProperty.PropertyType == typeof(string))
|
|
||||||
{
|
{
|
||||||
idProperty.SetValue(entity, Guid.NewGuid().ToString());
|
dict["Id"] = Guid.NewGuid().ToString();
|
||||||
|
}
|
||||||
|
else if (string.IsNullOrEmpty(dict["Id"]?.ToString()))
|
||||||
|
{
|
||||||
|
dict["Id"] = Guid.NewGuid().ToString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//如果Id不为空,需要判断Id是否存在
|
||||||
|
var entity = await _client.Queryable<dynamic>()
|
||||||
|
.AS(req.TableName)
|
||||||
|
.Where("Id = @id", new { id = dict["Id"] })
|
||||||
|
.FirstAsync();
|
||||||
|
if (entity != null)
|
||||||
|
{
|
||||||
|
result.Code = 500;
|
||||||
|
result.Message = "Id已存在";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var createTimeProperty = entityType.GetProperty("CreateTime");
|
//如果有CreateTime字段,自动设置
|
||||||
if (createTimeProperty != null && createTimeProperty.PropertyType == typeof(DateTime))
|
if (dict.ContainsKey("CreateTime"))
|
||||||
{
|
{
|
||||||
createTimeProperty.SetValue(entity, DateTime.Now);
|
dict["CreateTime"] = DateTime.Now;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果有用户信息,设置创建用户
|
// 添加数据
|
||||||
var currentUser = _auth.GetCurrentUser();
|
await _client.Insertable(dict)
|
||||||
if (currentUser != null)
|
.AS(req.TableName)
|
||||||
{
|
.ExecuteCommandAsync();
|
||||||
// 尝试设置创建用户信息
|
|
||||||
TrySetProperty(entity, "CreateUserId", currentUser.User.Id);
|
|
||||||
TrySetProperty(entity, "CreateUserName", currentUser.User.Name);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加实体
|
|
||||||
var insertMethod = _client.GetType().GetMethod("Insertable")
|
|
||||||
.MakeGenericMethod(entityType);
|
|
||||||
dynamic insertable = insertMethod.Invoke(_client, new[] { entity });
|
|
||||||
insertable.ExecuteCommand();
|
|
||||||
|
|
||||||
result.Message = "添加成功";
|
result.Message = "添加成功";
|
||||||
}
|
}
|
||||||
@ -190,46 +198,55 @@ namespace OpenAuth.App
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 更新实体
|
/// 更新表数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="entityName">实体名称,例如:ExternalDataSource</param>
|
/// <param name="tableName">表名称</param>
|
||||||
/// <param name="obj">实体对象</param>
|
/// <param name="obj">数据对象</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Infrastructure.Response Update(string entityName, object obj)
|
public async Task<Infrastructure.Response> Update(AddOrUpdateDynamicEntityReq req)
|
||||||
{
|
{
|
||||||
var result = new Infrastructure.Response();
|
var result = new Infrastructure.Response();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 获取实体类型
|
// 验证表名是否存在
|
||||||
var entityType = GetEntityType(entityName);
|
if (!TableExists(req.TableName))
|
||||||
if (entityType == null)
|
|
||||||
{
|
{
|
||||||
result.Code = 500;
|
result.Code = 500;
|
||||||
result.Message = $"未找到实体:{entityName}";
|
result.Message = $"表不存在:{req.TableName}";
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 将传入的对象转换为实体类型
|
// 将对象转换为字典
|
||||||
var entity = obj.MapTo(entityType);
|
var dict = req.Obj.ToDictionary();
|
||||||
|
|
||||||
// 设置更新信息
|
// 检查ID是否存在
|
||||||
// 尝试设置更新时间
|
if (!dict.ContainsKey("Id"))
|
||||||
TrySetProperty(entity, "UpdateTime", DateTime.Now);
|
{
|
||||||
|
result.Code = 500;
|
||||||
|
result.Message = "更新数据必须包含Id字段";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置更新时间
|
||||||
|
if (!dict.ContainsKey("UpdateTime"))
|
||||||
|
{
|
||||||
|
dict["UpdateTime"] = DateTime.Now;
|
||||||
|
}
|
||||||
|
|
||||||
// 如果有用户信息,设置更新用户
|
// 如果有用户信息,设置更新用户
|
||||||
var currentUser = _auth.GetCurrentUser();
|
var currentUser = _auth.GetCurrentUser();
|
||||||
if (currentUser != null)
|
if (dict.ContainsKey("UpdateUserId") && currentUser != null)
|
||||||
{
|
{
|
||||||
// 尝试设置更新用户信息
|
// 设置更新用户信息
|
||||||
TrySetProperty(entity, "UpdateUserId", currentUser.User.Id);
|
dict["UpdateUserId"] = currentUser.User.Id;
|
||||||
TrySetProperty(entity, "UpdateUserName", currentUser.User.Name);
|
dict["UpdateUserName"] = currentUser.User.Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新实体
|
// 更新数据
|
||||||
var updateMethod = _client.GetType().GetMethod("Updateable")
|
await _client.Updateable(dict)
|
||||||
.MakeGenericMethod(entityType);
|
.AS(req.TableName)
|
||||||
dynamic updateable = updateMethod.Invoke(_client, new[] { entity });
|
.Where("Id = @id", new { id = dict["Id"] })
|
||||||
updateable.ExecuteCommand();
|
.ExecuteCommandAsync();
|
||||||
|
|
||||||
result.Message = "更新成功";
|
result.Message = "更新成功";
|
||||||
}
|
}
|
||||||
@ -243,97 +260,29 @@ namespace OpenAuth.App
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 删除实体
|
/// 批量删除表数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="entityName">实体名称,例如:ExternalDataSource</param>
|
/// <param name="tableName">表名称</param>
|
||||||
/// <param name="id">实体ID</param>
|
/// <param name="ids">记录ID数组</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Infrastructure.Response Delete(string entityName, string id)
|
public async Task<Infrastructure.Response> Delete(DelDynamicReq req)
|
||||||
{
|
{
|
||||||
var result = new Infrastructure.Response();
|
var result = new Infrastructure.Response();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 获取实体类型
|
// 验证表名是否存在
|
||||||
var entityType = GetEntityType(entityName);
|
if (!TableExists(req.TableName))
|
||||||
if (entityType == null)
|
|
||||||
{
|
{
|
||||||
result.Code = 500;
|
result.Code = 500;
|
||||||
result.Message = $"未找到实体:{entityName}";
|
result.Message = $"表不存在:{req.TableName}";
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建动态查询
|
// 批量删除数据
|
||||||
dynamic queryable = _client.GetType().GetMethod("Queryable", new Type[] { })
|
await _client.Deleteable<dynamic>()
|
||||||
.MakeGenericMethod(entityType)
|
.AS(req.TableName)
|
||||||
.Invoke(_client, null);
|
.Where("Id in (@ids)", new { ids = req.Ids })
|
||||||
|
.ExecuteCommandAsync();
|
||||||
// 获取要删除的实体
|
|
||||||
var entity = queryable.Where("Id = @id", new { id }).First();
|
|
||||||
|
|
||||||
if (entity == null)
|
|
||||||
{
|
|
||||||
result.Code = 500;
|
|
||||||
result.Message = "未找到要删除的实体";
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除实体
|
|
||||||
var deleteMethod = _client.GetType().GetMethod("Deleteable")
|
|
||||||
.MakeGenericMethod(entityType);
|
|
||||||
dynamic deleteable = deleteMethod.Invoke(_client, new[] { entity });
|
|
||||||
deleteable.ExecuteCommand();
|
|
||||||
|
|
||||||
result.Message = "删除成功";
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
result.Code = 500;
|
|
||||||
result.Message = ex.InnerException?.Message ?? ex.Message;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 批量删除实体
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="entityName">实体名称,例如:ExternalDataSource</param>
|
|
||||||
/// <param name="ids">实体ID数组</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public Infrastructure.Response BatchDelete(string entityName, string[] ids)
|
|
||||||
{
|
|
||||||
var result = new Infrastructure.Response();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// 获取实体类型
|
|
||||||
var entityType = GetEntityType(entityName);
|
|
||||||
if (entityType == null)
|
|
||||||
{
|
|
||||||
result.Code = 500;
|
|
||||||
result.Message = $"未找到实体:{entityName}";
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建动态查询
|
|
||||||
dynamic queryable = _client.GetType().GetMethod("Queryable", new Type[] { })
|
|
||||||
.MakeGenericMethod(entityType)
|
|
||||||
.Invoke(_client, null);
|
|
||||||
|
|
||||||
// 获取要删除的实体列表
|
|
||||||
var entities = queryable.Where("Id in (@ids)", new { ids }).ToList();
|
|
||||||
|
|
||||||
if (entities == null || entities.Count == 0)
|
|
||||||
{
|
|
||||||
result.Code = 500;
|
|
||||||
result.Message = "未找到要删除的实体";
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 批量删除实体
|
|
||||||
var deleteMethod = _client.GetType().GetMethod("Deleteable")
|
|
||||||
.MakeGenericMethod(entityType);
|
|
||||||
dynamic deleteable = deleteMethod.Invoke(_client, new[] { entities });
|
|
||||||
deleteable.ExecuteCommand();
|
|
||||||
|
|
||||||
result.Message = "批量删除成功";
|
result.Message = "批量删除成功";
|
||||||
}
|
}
|
||||||
@ -347,37 +296,82 @@ namespace OpenAuth.App
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取实体类型
|
/// 检查表是否存在
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="entityName">实体名称</param>
|
/// <param name="tableName">表名</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private Type GetEntityType(string entityName)
|
private bool TableExists(string tableName)
|
||||||
{
|
{
|
||||||
// 获取所有实体类型
|
// 获取数据库类型
|
||||||
var entityTypes = typeof(StringEntity).Assembly.GetTypes()
|
var dbType = _client.CurrentConnectionConfig.DbType;
|
||||||
.Where(t => t.IsClass && !t.IsAbstract && t.IsSubclassOf(typeof(StringEntity)))
|
string sql = string.Empty;
|
||||||
.ToList();
|
|
||||||
|
|
||||||
// 查找匹配的实体类型
|
switch (dbType)
|
||||||
return entityTypes.FirstOrDefault(t =>
|
{
|
||||||
t.Name.Equals(entityName, StringComparison.OrdinalIgnoreCase));
|
case DbType.SqlServer:
|
||||||
|
sql = $"SELECT COUNT(1) FROM sys.tables WHERE name = '{tableName}'";
|
||||||
|
break;
|
||||||
|
case DbType.MySql:
|
||||||
|
sql = $"SELECT COUNT(1) FROM information_schema.tables WHERE table_name = '{tableName}' AND table_schema = DATABASE()";
|
||||||
|
break;
|
||||||
|
case DbType.PostgreSQL:
|
||||||
|
sql = $"SELECT COUNT(1) FROM pg_tables WHERE tablename = '{tableName.ToLower()}'";
|
||||||
|
break;
|
||||||
|
case DbType.Oracle:
|
||||||
|
sql = $"SELECT COUNT(1) FROM user_tables WHERE table_name = '{tableName.ToUpper()}'";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new NotSupportedException($"不支持的数据库类型:{dbType}");
|
||||||
|
}
|
||||||
|
|
||||||
|
var count = _client.Ado.GetInt(sql);
|
||||||
|
return count > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 尝试设置属性值
|
/// 获取表字段信息
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tableName">表名</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private List<DbColumnInfo> GetTableColumns(string tableName)
|
||||||
|
{
|
||||||
|
return _client.DbMaintenance.GetColumnInfosByTableName(tableName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 对象扩展方法
|
||||||
|
/// </summary>
|
||||||
|
public static class ObjectExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 将对象转换为字典
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="obj">对象</param>
|
/// <param name="obj">对象</param>
|
||||||
/// <param name="propertyName">属性名</param>
|
/// <returns></returns>
|
||||||
/// <param name="value">属性值</param>
|
public static Dictionary<string, object> ToDictionary(this object obj)
|
||||||
private void TrySetProperty(object obj, string propertyName, object value)
|
|
||||||
{
|
{
|
||||||
var property = obj.GetType().GetProperty(propertyName,
|
var dict = new Dictionary<string, object>();
|
||||||
BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
|
|
||||||
|
|
||||||
if (property != null && property.CanWrite)
|
if (obj == null) return dict;
|
||||||
|
|
||||||
|
// 如果已经是字典类型,直接返回
|
||||||
|
if (obj is Dictionary<string, object> dictionary)
|
||||||
{
|
{
|
||||||
property.SetValue(obj, value);
|
return dictionary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取所有属性
|
||||||
|
foreach (var prop in obj.GetType().GetProperties())
|
||||||
|
{
|
||||||
|
var value = prop.GetValue(obj);
|
||||||
|
if (value != null)
|
||||||
|
{
|
||||||
|
dict[prop.Name] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dict;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
namespace OpenAuth.App.Request
|
||||||
|
{
|
||||||
|
public class AddOrUpdateDynamicEntityReq
|
||||||
|
{
|
||||||
|
public string TableName { get; set; }
|
||||||
|
|
||||||
|
public object Obj { get; set; }
|
||||||
|
}
|
||||||
|
}
|
9
OpenAuth.App/DynamicApiApp/Request/DelDynamicReq.cs
Normal file
9
OpenAuth.App/DynamicApiApp/Request/DelDynamicReq.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace OpenAuth.App.Request
|
||||||
|
{
|
||||||
|
public class DelDynamicReq
|
||||||
|
{
|
||||||
|
public string TableName { get; set; }
|
||||||
|
|
||||||
|
public string[] Ids { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
namespace OpenAuth.App.Request
|
||||||
|
{
|
||||||
|
public class QueryDynamicEntityReq
|
||||||
|
{
|
||||||
|
public string TableName { get; set; }
|
||||||
|
|
||||||
|
public string Id { get; set; }
|
||||||
|
}
|
||||||
|
}
|
10
OpenAuth.App/DynamicApiApp/Request/QueryDynamicListReq.cs
Normal file
10
OpenAuth.App/DynamicApiApp/Request/QueryDynamicListReq.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
namespace OpenAuth.App.Request
|
||||||
|
{
|
||||||
|
public class QueryDynamicListReq: PageReq
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 表名
|
||||||
|
/// </summary>
|
||||||
|
public string TableName { get; set; }
|
||||||
|
}
|
||||||
|
}
|
77
OpenAuth.App/Test/TestDynamicApiApp.cs
Normal file
77
OpenAuth.App/Test/TestDynamicApiApp.cs
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Infrastructure;
|
||||||
|
using Infrastructure.Cache;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Moq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using OpenAuth.App.Request;
|
||||||
|
using OpenAuth.App.SSO;
|
||||||
|
|
||||||
|
namespace OpenAuth.App.Test
|
||||||
|
{
|
||||||
|
class TestDynamicApiApp :TestBase
|
||||||
|
{
|
||||||
|
public override ServiceCollection GetService()
|
||||||
|
{
|
||||||
|
var services = new ServiceCollection();
|
||||||
|
|
||||||
|
var cachemock = new Mock<ICacheContext>();
|
||||||
|
cachemock.Setup(x => x.Get<UserAuthSession>("tokentest")).Returns(new UserAuthSession { Account = "test" });
|
||||||
|
services.AddScoped(x => cachemock.Object);
|
||||||
|
|
||||||
|
var httpContextAccessorMock = new Mock<IHttpContextAccessor>();
|
||||||
|
httpContextAccessorMock.Setup(x => x.HttpContext.Request.Query[Define.TOKEN_NAME]).Returns("tokentest");
|
||||||
|
|
||||||
|
services.AddScoped(x => httpContextAccessorMock.Object);
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task TestGet()
|
||||||
|
{
|
||||||
|
var app = _autofacServiceProvider.GetService<DynamicApiApp>();
|
||||||
|
|
||||||
|
var obj = await app.Get(new QueryDynamicEntityReq { TableName = "noentity", Id = "1" });
|
||||||
|
Console.WriteLine(JsonHelper.Instance.Serialize(obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task TestGetList()
|
||||||
|
{
|
||||||
|
var app = _autofacServiceProvider.GetService<DynamicApiApp>();
|
||||||
|
|
||||||
|
var obj = await app.GetList(new QueryDynamicListReq { TableName = "noentity", page = 1, limit = 10, key = "" });
|
||||||
|
Console.WriteLine(JsonHelper.Instance.Serialize(obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task TestAdd()
|
||||||
|
{
|
||||||
|
var app = _autofacServiceProvider.GetService<DynamicApiApp>();
|
||||||
|
|
||||||
|
var obj = await app.Add(new AddOrUpdateDynamicEntityReq { TableName = "noentity", Obj = new { Id = "10", P1 = DateTime.Now.ToString() } });
|
||||||
|
Console.WriteLine(JsonHelper.Instance.Serialize(obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task TestUpdate()
|
||||||
|
{
|
||||||
|
var app = _autofacServiceProvider.GetService<DynamicApiApp>();
|
||||||
|
|
||||||
|
var obj = await app.Update(new AddOrUpdateDynamicEntityReq { TableName = "noentity", Obj = new { Id = "1", P1 = DateTime.Now.ToString() } });
|
||||||
|
Console.WriteLine(JsonHelper.Instance.Serialize(obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task TestDelete()
|
||||||
|
{
|
||||||
|
var app = _autofacServiceProvider.GetService<DynamicApiApp>();
|
||||||
|
|
||||||
|
var obj = await app.Delete(new DelDynamicReq() { TableName = "noentity", Ids = new string[] { "10" } });
|
||||||
|
Console.WriteLine(JsonHelper.Instance.Serialize(obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,16 +4,18 @@ using Infrastructure;
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using OpenAuth.App;
|
using OpenAuth.App;
|
||||||
using OpenAuth.App.Response;
|
using OpenAuth.App.Response;
|
||||||
|
using OpenAuth.App.Request;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
|
||||||
namespace OpenAuth.WebApi.Controllers
|
namespace OpenAuth.WebApi.Controllers
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 动态实体API控制器
|
/// 动态API控制器
|
||||||
/// 用于处理任意实体的CRUD操作
|
/// 用于处理任意表的CRUD操作
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("api/dynamic/[action]")]
|
[Route("api/dynamic/[action]")]
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[ApiExplorerSettings(GroupName = "动态API_DynamicEntity")]
|
[ApiExplorerSettings(GroupName = "动态API_DynamicApi")]
|
||||||
public class DynamicApiController : ControllerBase
|
public class DynamicApiController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly DynamicApiApp _app;
|
private readonly DynamicApiApp _app;
|
||||||
@ -24,21 +26,19 @@ namespace OpenAuth.WebApi.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取实体列表
|
/// 获取表数据列表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="entityName">实体名称,例如:ExternalDataSource</param>
|
/// <param name="req">查询参数</param>
|
||||||
/// <param name="page">页码</param>
|
|
||||||
/// <param name="limit">每页记录数</param>
|
|
||||||
/// <param name="key">搜索关键字</param>
|
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpGet]
|
[HttpPost]
|
||||||
public async Task<TableData> GetList(string entityName, int page = 1, int limit = 10, string key = "")
|
[AllowAnonymous]
|
||||||
|
public async Task<TableData> GetList([FromBody] QueryDynamicListReq req)
|
||||||
{
|
{
|
||||||
TableData result = new TableData();
|
TableData result = new TableData();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 获取实体类型
|
// 获取实体类型
|
||||||
result = await _app.GetList(entityName, page, limit, key);
|
result = await _app.GetList(req);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -50,19 +50,19 @@ namespace OpenAuth.WebApi.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取实体详情
|
/// 获取表数据详情
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="entityName">实体名称,例如:ExternalDataSource</param>
|
/// <param name="req">查询参数</param>
|
||||||
/// <param name="id">实体ID</param>
|
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpGet]
|
[HttpPost]
|
||||||
public Response<object> Get(string entityName, string id)
|
[AllowAnonymous]
|
||||||
|
public async Task<Response<object>> Get([FromBody] QueryDynamicEntityReq req)
|
||||||
{
|
{
|
||||||
var result = new Response<object>();
|
var result = new Response<object>();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 获取实体类型
|
// 获取实体类型
|
||||||
result = _app.Get(entityName, id);
|
result = await _app.Get(req);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -74,19 +74,19 @@ namespace OpenAuth.WebApi.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 添加实体
|
/// 添加表数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="entityName">实体名称,例如:ExternalDataSource</param>
|
/// <param name="req">添加参数</param>
|
||||||
/// <param name="obj">实体对象</param>
|
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public Response Add(string entityName, [FromBody] object obj)
|
[AllowAnonymous]
|
||||||
|
public async Task<Response> Add([FromBody] AddOrUpdateDynamicEntityReq req)
|
||||||
{
|
{
|
||||||
var result = new Response();
|
var result = new Response();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 获取实体类型
|
// 获取实体类型
|
||||||
result = _app.Add(entityName, obj);
|
result = await _app.Add(req);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -104,37 +104,14 @@ namespace OpenAuth.WebApi.Controllers
|
|||||||
/// <param name="obj">实体对象</param>
|
/// <param name="obj">实体对象</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public Response Update(string entityName, [FromBody] object obj)
|
[AllowAnonymous]
|
||||||
|
public async Task<Response> Update([FromBody] AddOrUpdateDynamicEntityReq req)
|
||||||
{
|
{
|
||||||
var result = new Response();
|
var result = new Response();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 获取实体类型
|
// 获取实体类型
|
||||||
result = _app.Update(entityName, obj);
|
result = await _app.Update(req);
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
result.Code = 500;
|
|
||||||
result.Message = ex.InnerException?.Message ?? ex.Message;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 删除实体
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="entityName">实体名称,例如:ExternalDataSource</param>
|
|
||||||
/// <param name="id">实体ID</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[HttpPost]
|
|
||||||
public Response Delete(string entityName, string id)
|
|
||||||
{
|
|
||||||
var result = new Response();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// 获取实体类型
|
|
||||||
result = _app.Delete(entityName, id);
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -152,13 +129,13 @@ namespace OpenAuth.WebApi.Controllers
|
|||||||
/// <param name="ids">实体ID数组</param>
|
/// <param name="ids">实体ID数组</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public Response BatchDelete(string entityName, [FromBody] string[] ids)
|
[AllowAnonymous]
|
||||||
|
public async Task<Response> Delete([FromBody] DelDynamicReq req)
|
||||||
{
|
{
|
||||||
var result = new Response();
|
var result = new Response();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 获取实体类型
|
result = await _app.Delete(req);
|
||||||
result = _app.BatchDelete(entityName, ids);
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user