using Admin.Core.Common.Attributes;
using Admin.Core.Common.Auth;
using Admin.Core.Common.BaseModel;
using Admin.Core.Common.Configs;
using Admin.Core.Common.Extensions;
using Admin.Core.Common.Helpers;
using Admin.Core.Model.Admin;
using Admin.Core.Model.Personnel;
using Admin.Core.Repository.Admin.Output;
using Admin.Core.Repository.Admin.Permission.Output;
using Admin.Core.Repository.Admin.View.Output;
using Admin.Core.Repository.Personnel.Output;
using FreeSql;
using FreeSql.Aop;
using FreeSql.DataAnnotations;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Yitter.IdGenerator;
namespace Admin.Core.Repository
{
public class DbHelper
{
///
/// 偏移时间
///
public static TimeSpan TimeOffset;
///
/// 创建数据库
///
///
///
public async static Task CreateDatabaseAsync(DbConfig dbConfig)
{
if (!dbConfig.CreateDb || dbConfig.Type == DataType.Sqlite)
{
return;
}
var db = new FreeSqlBuilder()
.UseConnectionString(dbConfig.Type, dbConfig.CreateDbConnectionString)
.Build();
try
{
Console.WriteLine("\r\n create database started");
await db.Ado.ExecuteNonQueryAsync(dbConfig.CreateDbSql);
Console.WriteLine(" create database succeed");
}
catch (Exception e)
{
Console.WriteLine($" create database failed.\n {e.Message}");
}
}
///
/// 获得指定程序集表实体
///
///
public static Type[] GetEntityTypes()
{
List assemblyNames = new List()
{
"Admin.Core.Model"
};
List entityTypes = new List();
foreach (var assemblyName in assemblyNames)
{
foreach (Type type in Assembly.Load(assemblyName).GetExportedTypes())
{
foreach (Attribute attribute in type.GetCustomAttributes())
{
if (attribute is TableAttribute tableAttribute)
{
if (tableAttribute.DisableSyncStructure == false)
{
entityTypes.Add(type);
}
}
}
}
}
return entityTypes.ToArray();
}
///
/// 配置实体
///
public static void ConfigEntity(IFreeSql db, AppConfig appConfig = null)
{
//租户生成和操作租户Id
if (!appConfig.Tenant)
{
var iTenant = nameof(ITenant);
var tenantId = nameof(ITenant.TenantId);
//获得指定程序集表实体
var entityTypes = GetEntityTypes();
foreach (var entityType in entityTypes)
{
if (entityType.GetInterfaces().Any(a => a.Name == iTenant))
{
db.CodeFirst.Entity(entityType, a =>
{
a.Ignore(tenantId);
});
}
}
}
}
///
/// 审计数据
///
///
///
///
public static void AuditValue(AuditValueEventArgs e, TimeSpan timeOffset, IUser user)
{
if (e.Property.GetCustomAttribute(false) != null
&& (e.Column.CsType == typeof(DateTime) || e.Column.CsType == typeof(DateTime?))
&& (e.Value == null || (DateTime)e.Value == default || (DateTime?)e.Value == default))
{
e.Value = DateTime.Now.Subtract(timeOffset);
}
if (e.Column.CsType == typeof(long)
&& e.Property.GetCustomAttribute(false) is SnowflakeAttribute snowflakeAttribute
&& snowflakeAttribute.Enable && (e.Value == null || (long)e.Value == default || (long?)e.Value == default))
{
e.Value = YitIdHelper.NextId();
}
if (user == null || user.Id <= 0)
{
return;
}
if (e.AuditValueType == AuditValueType.Insert)
{
switch (e.Property.Name)
{
case "CreatedUserId":
if (e.Value == null || (long)e.Value == default || (long?)e.Value == default)
{
e.Value = user.Id;
}
break;
case "CreatedUserName":
if (e.Value == null || ((string)e.Value).IsNull())
{
e.Value = user.Name;
}
break;
case "TenantId":
if (e.Value == null || (long)e.Value == default || (long?)e.Value == default)
{
e.Value = user.TenantId;
}
break;
}
}
else if (e.AuditValueType == AuditValueType.Update)
{
switch (e.Property.Name)
{
case "ModifiedUserId":
e.Value = user.Id;
break;
case "ModifiedUserName":
e.Value = user.Name;
break;
}
}
}
///
/// 同步结构
///
public static void SyncStructure(IFreeSql db, string msg = null, DbConfig dbConfig = null, AppConfig appConfig = null)
{
//打印结构比对脚本
//var dDL = db.CodeFirst.GetComparisonDDLStatements();
//Console.WriteLine("\r\n " + dDL);
//打印结构同步脚本
//db.Aop.SyncStructureAfter += (s, e) =>
//{
// if (e.Sql.NotNull())
// {
// Console.WriteLine(" sync structure sql:\n" + e.Sql);
// }
//};
// 同步结构
var dbType = dbConfig.Type.ToString();
Console.WriteLine($"\r\n {(msg.NotNull() ? msg : $"sync {dbType} structure")} started");
if (dbConfig.Type == DataType.Oracle)
{
db.CodeFirst.IsSyncStructureToUpper = true;
}
//获得指定程序集表实体
var entityTypes = GetEntityTypes();
db.CodeFirst.SyncStructure(entityTypes);
Console.WriteLine($" {(msg.NotNull() ? msg : $"sync {dbType} structure")} succeed");
}
///
/// 检查实体属性是否为自增长
///
///
///
private static bool CheckIdentity() where T : class
{
var isIdentity = false;
var properties = typeof(T).GetProperties();
foreach (var property in properties)
{
if (property.GetCustomAttributes(typeof(ColumnAttribute), false).FirstOrDefault() is ColumnAttribute columnAttribute && columnAttribute.IsIdentity)
{
isIdentity = true;
break;
}
}
return isIdentity;
}
///
/// 初始化数据表数据
///
///
///
///
///
///
///
///
private static async Task InitDtDataAsync(
IFreeSql db,
IUnitOfWork unitOfWork,
System.Data.Common.DbTransaction tran,
T[] data,
DbConfig dbConfig = null
) where T : class, new()
{
var table = typeof(T).GetCustomAttributes(typeof(TableAttribute), false).FirstOrDefault() as TableAttribute;
var tableName = table.Name;
try
{
if (await db.Queryable().AnyAsync())
{
Console.WriteLine($" table: {tableName} record already exists");
return;
}
if (!(data?.Length > 0))
{
Console.WriteLine($" table: {tableName} import data []");
return;
}
var repo = db.GetRepositoryBase();
var insert = db.Insert();
if (unitOfWork != null)
{
repo.UnitOfWork = unitOfWork;
insert = insert.WithTransaction(tran);
}
var isIdentity = CheckIdentity();
if (isIdentity)
{
if (dbConfig.Type == DataType.SqlServer)
{
var insrtSql = insert.AppendData(data).InsertIdentity().ToSql();
await repo.Orm.Ado.ExecuteNonQueryAsync($"SET IDENTITY_INSERT {tableName} ON\n {insrtSql} \nSET IDENTITY_INSERT {tableName} OFF");
}
else
{
await insert.AppendData(data).InsertIdentity().ExecuteAffrowsAsync();
}
}
else
{
repo.DbContextOptions.EnableAddOrUpdateNavigateList = true;
await repo.InsertAsync(data);
}
Console.WriteLine($" table: {tableName} sync data succeed");
}
catch (Exception ex)
{
Console.WriteLine($" table: {tableName} sync data failed.\n{ex.Message}");
}
}
///
/// 同步数据审计方法
///
///
///
private static void SyncDataAuditValue(object s, AuditValueEventArgs e)
{
var user = new { Id = 161223411986501, Name = "admin", TenantId = 161223412138053 };
if (e.Property.GetCustomAttribute(false) != null
&& (e.Column.CsType == typeof(DateTime) || e.Column.CsType == typeof(DateTime?))
&& (e.Value == null || (DateTime)e.Value == default || (DateTime?)e.Value == default))
{
e.Value = DateTime.Now.Subtract(TimeOffset);
}
if (e.Column.CsType == typeof(long)
&& e.Property.GetCustomAttribute(false) != null
&& (e.Value == null || (long)e.Value == default || (long?)e.Value == default))
{
e.Value = YitIdHelper.NextId();
}
if (user == null || user.Id <= 0)
{
return;
}
if (e.AuditValueType == AuditValueType.Insert)
{
switch (e.Property.Name)
{
case "CreatedUserId":
if (e.Value == null || (long)e.Value == default || (long?)e.Value == default)
{
e.Value = user.Id;
}
break;
case "CreatedUserName":
if (e.Value == null || ((string)e.Value).IsNull())
{
e.Value = user.Name;
}
break;
case "TenantId":
if (e.Value == null || (long)e.Value == default || (long?)e.Value == default)
{
e.Value = user.TenantId;
}
break;
}
}
else if (e.AuditValueType == AuditValueType.Update)
{
switch (e.Property.Name)
{
case "ModifiedUserId":
e.Value = user.Id;
break;
case "ModifiedUserName":
e.Value = user.Name;
break;
}
}
}
///
/// 同步数据
///
///
public static async Task SyncDataAsync(IFreeSql db, DbConfig dbConfig = null, AppConfig appConfig = null)
{
try
{
//db.Aop.CurdBefore += (s, e) =>
//{
// Console.WriteLine($"{e.Sql}\r\n");
//};
Console.WriteLine("\r\n sync data started");
db.Aop.AuditValue += SyncDataAuditValue;
var fileName = appConfig.Tenant ? "data-share.json" : "data.json";
var filePath = Path.Combine(AppContext.BaseDirectory, $"Db/Data/{fileName}").ToPath();
var jsonData = FileHelper.ReadFile(filePath);
var data = JsonConvert.DeserializeObject(jsonData);
using (var uow = db.CreateUnitOfWork())
using (var tran = uow.GetOrBeginTransaction())
{
var dualRepo = db.GetRepositoryBase();
dualRepo.UnitOfWork = uow;
if (!await dualRepo.Select.AnyAsync())
{
await dualRepo.InsertAsync(new DualEntity { });
}
//admin
await InitDtDataAsync(db, uow, tran, data.DictionaryTypes, dbConfig);
await InitDtDataAsync(db, uow, tran, data.Dictionaries, dbConfig);
await InitDtDataAsync(db, uow, tran, data.ApiTree, dbConfig);
await InitDtDataAsync(db, uow, tran, data.ViewTree, dbConfig);
await InitDtDataAsync(db, uow, tran, data.PermissionTree, dbConfig);
await InitDtDataAsync(db, uow, tran, data.Users, dbConfig);
await InitDtDataAsync(db, uow, tran, data.Roles, dbConfig);
await InitDtDataAsync(db, uow, tran, data.UserRoles, dbConfig);
await InitDtDataAsync(db, uow, tran, data.RolePermissions, dbConfig);
await InitDtDataAsync(db, uow, tran, data.Tenants, dbConfig);
await InitDtDataAsync(db, uow, tran, data.TenantPermissions, dbConfig);
await InitDtDataAsync(db, uow, tran, data.PermissionApis, dbConfig);
//人事
await InitDtDataAsync(db, uow, tran, data.Positions, dbConfig);
await InitDtDataAsync(db, uow, tran, data.OrganizationTree, dbConfig);
await InitDtDataAsync(db, uow, tran, data.Employees, dbConfig);
uow.Commit();
}
db.Aop.AuditValue -= SyncDataAuditValue;
Console.WriteLine(" sync data succeed\r\n");
}
catch (Exception ex)
{
throw new Exception($" sync data failed.\n{ex.Message}");
}
}
///
/// 生成极简数据
///
///
///
///
public static async Task GenerateSimpleJsonDataAsync(IFreeSql db, AppConfig appConfig = null)
{
try
{
Console.WriteLine("\r\n generate data started");
#region 数据表
//admin
#region 数据字典
var dictionaryTypes = await db.Queryable().ToListAsync();
var dictionaries = await db.Queryable().ToListAsync();
#endregion
#region 接口
var apis = await db.Queryable().ToListAsync();
var apiTree = apis.ToTree((r, c) =>
{
return c.ParentId == 0;
},
(r, c) =>
{
return r.Id == c.ParentId;
},
(r, datalist) =>
{
r.Childs ??= new List();
r.Childs.AddRange(datalist);
});
#endregion
#region 视图
var views = await db.Queryable().ToListAsync();
var viewTree = views.ToTree((r, c) =>
{
return c.ParentId == 0;
},
(r, c) =>
{
return r.Id == c.ParentId;
},
(r, datalist) =>
{
r.Childs ??= new List();
r.Childs.AddRange(datalist);
});
#endregion
#region 权限
var permissions = await db.Queryable().ToListAsync();
var permissionTree = permissions.ToTree((r, c) =>
{
return c.ParentId == 0;
},
(r, c) =>
{
return r.Id == c.ParentId;
},
(r, datalist) =>
{
r.Childs ??= new List();
r.Childs.AddRange(datalist);
});
#endregion
#region 用户
var users = await db.Queryable().ToListAsync();
#endregion
#region 角色
var roles = await db.Queryable().ToListAsync();
#endregion
#region 用户角色
var userRoles = await db.Queryable().ToListAsync(a => new
{
a.Id,
a.UserId,
a.RoleId
});
#endregion
#region 角色权限
var rolePermissions = await db.Queryable().ToListAsync(a => new
{
a.Id,
a.RoleId,
a.PermissionId
});
#endregion
#region 租户
var tenants = await db.Queryable().ToListAsync(a => new
{
a.Id,
a.UserId,
a.RoleId,
a.Name,
a.Code,
a.RealName,
a.Phone,
a.Email,
a.TenantType,
a.DataIsolationType,
a.DbType,
a.ConnectionString,
a.IdleTime,
a.Description
});
#endregion
#region 租户权限
var tenantPermissions = await db.Queryable().ToListAsync(a => new
{
a.Id,
a.TenantId,
a.PermissionId
});
#endregion
#region 权限接口
var permissionApis = await db.Queryable().ToListAsync(a => new
{
a.Id,
a.PermissionId,
a.ApiId
});
#endregion
//人事
#region 部门
var organizations = await db.Queryable().ToListAsync();
var organizationTree = organizations.ToTree((r, c) =>
{
return c.ParentId == 0;
},
(r, c) =>
{
return r.Id == c.ParentId;
},
(r, datalist) =>
{
r.Childs ??= new List();
r.Childs.AddRange(datalist);
});
#endregion
#region 岗位
var positions = await db.Queryable().ToListAsync();
#endregion
#region 员工
var employees = await db.Queryable().ToListAsync();
#endregion
#endregion
if (!(users?.Count > 0))
{
return;
}
#region 生成数据
var settings = new JsonSerializerSettings();
settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
settings.NullValueHandling = NullValueHandling.Ignore;
settings.DefaultValueHandling = DefaultValueHandling.Ignore;
var jsonData = JsonConvert.SerializeObject(new
{
dictionaries,
dictionaryTypes,
apis,
apiTree,
viewTree,
permissionTree,
users,
roles,
userRoles,
rolePermissions,
tenants,
tenantPermissions,
permissionApis,
organizationTree,
positions,
employees
},
//Formatting.Indented,
settings
);
var isTenant = appConfig.Tenant;
var fileName = isTenant ? "data-share.json" : "data.json";
var filePath = Path.Combine(Directory.GetCurrentDirectory(), $"Db/Data/{fileName}").ToPath();
FileHelper.WriteFile(filePath, jsonData);
if (isTenant)
{
var tenantId = tenants.Where(a => a.Code.ToLower() == "zhontai").FirstOrDefault().Id;
organizationTree = organizations.Where(a => a.TenantId == tenantId).ToList().ToTree((r, c) =>
{
return c.ParentId == 0;
},
(r, c) =>
{
return r.Id == c.ParentId;
},
(r, datalist) =>
{
r.Childs ??= new List();
r.Childs.AddRange(datalist);
});
jsonData = JsonConvert.SerializeObject(new
{
dictionaries = dictionaries.Where(a=>a.TenantId == tenantId),
dictionaryTypes = dictionaryTypes.Where(a => a.TenantId == tenantId),
apis,
apiTree,
viewTree,
permissionTree,
users = users.Where(a => a.TenantId == tenantId),
roles = roles.Where(a => a.TenantId == tenantId),
userRoles,
rolePermissions,
tenants,
tenantPermissions,
permissionApis,
organizationTree
},
settings
);
filePath = Path.Combine(Directory.GetCurrentDirectory(), "Db/Data/data.json").ToPath();
FileHelper.WriteFile(filePath, jsonData);
}
#endregion
Console.WriteLine(" generate data succeed\r\n");
}
catch (Exception ex)
{
throw new Exception($" generate data failed。\n{ex.Message}\r\n");
}
}
}
}