├── .DS_Store ├── .gitignore ├── LICENSE ├── MyStaging.sln ├── README.md ├── doc ├── README.md └── mystaging.sql ├── examples ├── .DS_Store ├── IdentityHost │ ├── .DS_Store │ ├── APIResult.cs │ ├── Controllers │ │ ├── AccountController.cs │ │ ├── BaseController.cs │ │ ├── PasswordController.cs │ │ ├── R2RController.cs │ │ ├── R2UController.cs │ │ ├── ResourceController.cs │ │ ├── RoleController.cs │ │ └── UserController.cs │ ├── Converters │ │ ├── JsonBooleanConverter.cs │ │ ├── JsonLowerCaseNamingPolicy.cs │ │ └── JsonUnixTimeConverter.cs │ ├── Extensions │ │ ├── CustomerAuthorizeFilter.cs │ │ ├── CustomerExceptionFilter.cs │ │ ├── JsonSerializerExtension.cs │ │ ├── RequestMiddleware.cs │ │ ├── StartupExtensions.cs │ │ └── SwaggerExtensions.cs │ ├── Helper │ │ ├── AesFactory.cs │ │ ├── HttpHelper.cs │ │ └── SecurityHelper.cs │ ├── IdentityHost.csproj │ ├── IdentityHost.csproj.user │ ├── IdentityHost.xml │ ├── Model │ │ ├── Article.cs │ │ ├── Customer.cs │ │ ├── IdentityHostDbContext.cs │ │ ├── M_Accesslog.cs │ │ ├── M_Mapping.cs │ │ ├── M_Resource.cs │ │ ├── M_Role.cs │ │ ├── M_Roleresource.cs │ │ └── M_User.cs │ ├── Program.cs │ ├── Properties │ │ ├── Resource.Designer.cs │ │ ├── Resource.resx │ │ └── launchSettings.json │ ├── Services │ │ ├── AccessLogService.cs │ │ ├── IManagerService.cs │ │ ├── ResourceService.cs │ │ ├── RoleService.cs │ │ └── UserService.cs │ ├── Startup.cs │ ├── ViewModel │ │ ├── IdViewModel.cs │ │ ├── LoginViewModel.cs │ │ ├── M_Resource.cs │ │ ├── PageViewModel.cs │ │ ├── PasswordViewModel.cs │ │ ├── R2EViewModel.cs │ │ ├── R2RViewModel.cs │ │ ├── ResourceViewModel.cs │ │ ├── RoleViewModel.cs │ │ └── UserViewModel.cs │ ├── appsettings.Development.json │ └── appsettings.json ├── Mysql │ ├── Model │ │ ├── Article.cs │ │ ├── Customer.cs │ │ ├── M_Accesslog.cs │ │ ├── M_Mapping.cs │ │ ├── M_Resource.cs │ │ ├── M_Role.cs │ │ ├── M_Roleresource.cs │ │ ├── M_User.cs │ │ └── MysqlDbContext.cs │ ├── ModelExt │ │ └── M_Resource.cs │ ├── Models.cs │ ├── Mysql.csproj │ ├── Mysql.csproj.user │ ├── Program.cs │ └── Services │ │ ├── ArticleService.cs │ │ └── ResourceService.cs └── Pgsql │ ├── ContextTest.cs │ ├── Model │ ├── Article.cs │ ├── PgsqlDbContext.cs │ ├── Post.cs │ ├── Topic.cs │ ├── Udt3.cs │ ├── User.cs │ └── _Enums.cs │ ├── Pgsql.csproj │ ├── Pgsql.csproj.user │ └── Program.cs ├── src ├── MyStaging.Gen │ ├── MyStaging.Gen.csproj │ ├── MyStaging.Gen.csproj.user │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ └── build.bat ├── MyStaging.MySql │ ├── Core │ │ ├── DeleteBuilder`.cs │ │ ├── InsertBuilder`.cs │ │ ├── SelectBuilder`.cs │ │ └── UpdateBuilder`.cs │ ├── Generals │ │ ├── EntityGeneral.cs │ │ └── GeneralFactory.cs │ ├── MySqlStagingConnection.cs │ ├── MyStaging.MySql.csproj │ ├── MyStaging.MySql.csproj.user │ └── MysqlType.cs ├── MyStaging.PostgreSQL │ ├── Core │ │ ├── DeleteBuilder`.cs │ │ ├── InsertBuilder`.cs │ │ ├── SelectBuilder`.cs │ │ └── UpdateBuilder`.cs │ ├── Generals │ │ ├── EntityGeneral.cs │ │ └── GeneralFactory.cs │ ├── MyStaging.PostgreSQL.csproj │ ├── PgStagingConnection.cs │ └── PgsqlType.cs └── MyStaging │ ├── Common │ ├── CheckNotNull.cs │ ├── MyStagingUtils.cs │ ├── ObjectId.cs │ └── ObjectIdFactory.cs │ ├── Core │ ├── ConnectionManager.cs │ ├── DbContext.cs │ ├── DbExpressionVisitor.cs │ ├── DbRecord.cs │ ├── DbSet`.cs │ ├── ExpressionCondition`.cs │ └── SQLExecute.cs │ ├── DataAnnotations │ └── PrimaryKeyAttribute.cs │ ├── Function │ └── SqlFunction.cs │ ├── Interface │ ├── Core │ │ ├── IDeleteBuilder`.cs │ │ ├── IInsertBuilder`.cs │ │ ├── ISelectBuilder`.cs │ │ └── IUpdateBuilder`.cs │ ├── IGeneralFactory.cs │ ├── IQueryPipeLine.cs │ ├── ISaveChanged.cs │ └── IStagingConnection.cs │ ├── Metadata │ ├── ConnectionModel.cs │ ├── ConstraintInfo.cs │ ├── ConstraintType.cs │ ├── DbFieldInfo.cs │ ├── EnumTypeInfo.cs │ ├── ExpressionInfo.cs │ ├── ExpressionUnionInfo.cs │ ├── GeneralConfig.cs │ ├── GeneralInfo.cs │ ├── ProjectConfig.cs │ ├── ProviderType.cs │ ├── StagingOptions.cs │ ├── TableInfo.cs │ ├── TableType.cs │ └── UnionType.cs │ ├── MyStaging.csproj │ └── MyStaging.csproj.user └── test ├── MyStaging.xUnitTest.db ├── DAL │ └── Build │ │ ├── Article.cs │ │ ├── Post.cs │ │ ├── Topic.cs │ │ └── User.cs ├── Model │ └── Build │ │ ├── ArticleModel.cs │ │ ├── PostModel.cs │ │ ├── TopicModel.cs │ │ ├── UserModel.cs │ │ └── _Enums.cs ├── MyStaging.xUnitTest.db.csproj └── _startup.cs └── MyStaging.xUnitTest ├── Common ├── CheckNotNullTest.cs └── MyStagingUtilsTest.cs ├── ConstantUtil.cs ├── Core ├── ConnectionManagerTest.cs ├── DbContextTest.cs ├── DbExpressionVisitorTest.cs └── SQLExecuteTest.cs ├── Models └── UserModel.cs ├── MyStaging.xUnitTest.csproj └── MyStaging.xUnitTest.sln /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lianggx/mystaging/b87f7c7b7f65f223e07ac0afd2befccae1eddf24/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # 此 .gitignore 文件已由 Microsoft(R) Visual Studio 自动创建。 3 | ################################################################################ 4 | 5 | *.dtbcache 6 | /*/*/bin 7 | /*/*/obj 8 | *.nupkg 9 | .vs/ 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 gus.liang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /doc/mystaging.sql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lianggx/mystaging/b87f7c7b7f65f223e07ac0afd2befccae1eddf24/doc/mystaging.sql -------------------------------------------------------------------------------- /examples/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lianggx/mystaging/b87f7c7b7f65f223e07ac0afd2befccae1eddf24/examples/.DS_Store -------------------------------------------------------------------------------- /examples/IdentityHost/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lianggx/mystaging/b87f7c7b7f65f223e07ac0afd2befccae1eddf24/examples/IdentityHost/.DS_Store -------------------------------------------------------------------------------- /examples/IdentityHost/APIResult.cs: -------------------------------------------------------------------------------- 1 | using IdentityHost.Extensions; 2 | using Microsoft.AspNetCore.Mvc; 3 | using System.Collections; 4 | using System.Text.Json; 5 | using System.Text.Json.Serialization; 6 | using System.Threading.Tasks; 7 | 8 | namespace IdentityHost 9 | { 10 | public partial class APIResult : ContentResult 11 | { 12 | [JsonPropertyName("code")] public int Code { get; set; } 13 | [JsonPropertyName("message")] public string Message { get; set; } 14 | [JsonPropertyName("data")] public Hashtable Data { get; set; } = new Hashtable(); 15 | 16 | public APIResult() { } 17 | 18 | public APIResult(int code, string message, params object[] data) 19 | { 20 | Code = code; 21 | Message = message; 22 | AppendData(data); 23 | } 24 | 25 | public APIResult SetCode(int code) { Code = code; return this; } 26 | 27 | public APIResult SetMessage(string message) { Message = message; return this; } 28 | 29 | public APIResult SetData(params object[] value) { Data.Clear(); return AppendData(value); } 30 | 31 | public APIResult AppendData(params object[] value) 32 | { 33 | if (value == null || value.Length < 2 || value[0] == null) return this; 34 | for (int a = 0; a < value.Length; a += 2) 35 | { 36 | if (value[a] == null) continue; 37 | Data[value[a]] = a + 1 < value.Length ? value[a + 1] : null; 38 | } 39 | return this; 40 | } 41 | 42 | private void WriteResult() 43 | { 44 | var data = new Hashtable { 45 | { "code",Code}, 46 | {"message",Message }, 47 | {"data",Data } 48 | }; 49 | 50 | ContentType = "application/json;charset=utf-8;"; 51 | //Content = JsonSerializer.Serialize(data, JsonSerializerExtension.JsonOptions); 52 | Content = JsonSerializer.Serialize(data); 53 | } 54 | 55 | public override void ExecuteResult(ActionContext context) 56 | { 57 | WriteResult(); 58 | base.ExecuteResult(context); 59 | } 60 | 61 | public override async Task ExecuteResultAsync(ActionContext context) 62 | { 63 | WriteResult(); 64 | await base.ExecuteResultAsync(context); 65 | } 66 | 67 | public const int OK = 0; 68 | 69 | /// 70 | /// 成功 0 71 | /// 72 | public static APIResult 成功 { get { return new APIResult(0, "成功"); } } 73 | /// 74 | /// 失败 99 75 | /// 76 | public static APIResult 失败 { get { return new APIResult(99, "失败"); } } 77 | /// 78 | /// 记录不存在 98 79 | /// 80 | public static APIResult 记录不存在 { get { return new APIResult(98, "记录不存在"); } } 81 | /// 82 | /// 参数格式不正确 97 83 | /// 84 | public static APIResult 参数格式不正确 { get { return new APIResult(97, "参数格式不正确"); } } 85 | /// 86 | /// 没有访问权限 96 87 | /// 88 | public static APIResult 没有访问权限 { get { return new APIResult(96, "没有访问权限"); } } 89 | /// 90 | /// 系统内置_内部异常 5001000 91 | /// 92 | public static APIResult 系统内置_内部异常 => new APIResult(5001000, "抱歉,访问出现错误了"); 93 | /// 94 | /// 用户_未登录 1001005 95 | /// 96 | public static APIResult 用户_未登录 => new APIResult(1001005, "未登录"); 97 | } 98 | } -------------------------------------------------------------------------------- /examples/IdentityHost/Controllers/BaseController.cs: -------------------------------------------------------------------------------- 1 | using IdentityHost.Model; 2 | using IdentityHost.Services; 3 | using Microsoft.AspNetCore.Cors; 4 | using Microsoft.AspNetCore.Http; 5 | using Microsoft.AspNetCore.Mvc; 6 | using Microsoft.AspNetCore.Mvc.Filters; 7 | using Microsoft.Extensions.Configuration; 8 | using Microsoft.Extensions.Logging; 9 | using StackExchange.Redis; 10 | using System; 11 | using System.Collections.Generic; 12 | using System.Linq; 13 | using System.Text.Json; 14 | 15 | namespace IdentityHost.Controllers 16 | { 17 | [EnableCors("all")] 18 | public class BaseController : Controller 19 | { 20 | protected const string SignInKey = "SignInKey_"; 21 | protected readonly IEnumerable managerServices; 22 | protected readonly ConnectionMultiplexer redisClient; 23 | 24 | public IConfiguration Cfg { get; } 25 | public ILogger Log { get; } 26 | 27 | public BaseController(IConfiguration cfg, ILogger logger, IEnumerable managerServices, ConnectionMultiplexer multiplexer) 28 | { 29 | this.Cfg = cfg; 30 | this.Log = logger; 31 | this.managerServices = managerServices; 32 | redisClient = multiplexer; 33 | } 34 | 35 | [FromHeader(Name = "token")] 36 | public string Token { get; set; } 37 | 38 | private M_User loginUser = null; 39 | 40 | public M_User LoginUser 41 | { 42 | get 43 | { 44 | if (loginUser != null) 45 | return loginUser; 46 | 47 | if (!string.IsNullOrEmpty(Token)) 48 | { 49 | int.TryParse(redisClient.GetDatabase().StringGet(SignInKey + Token), out int userId); 50 | if (userId > 0) 51 | { 52 | loginUser = GetService().Detail(userId); 53 | } 54 | 55 | return loginUser; 56 | } 57 | else 58 | { 59 | throw new Exception("未登录"); 60 | } 61 | } 62 | } 63 | 64 | public string IP => this.Request.Headers["X-Real-IP"].FirstOrDefault() ?? this.Request.HttpContext.Connection.RemoteIpAddress?.ToString(); 65 | 66 | public T GetService() => (T)managerServices.FirstOrDefault(f => f.ServiceName == typeof(T).Name); 67 | 68 | private M_Resource resource; 69 | 70 | public override void OnActionExecuting(ActionExecutingContext context) 71 | { 72 | var path = context.HttpContext.Request.Path.Value; 73 | resource = GetService().Detail(path); 74 | if (context.ModelState.IsValid == false) 75 | { 76 | foreach (var value in context.ModelState.Values) 77 | if (value.Errors.Any()) 78 | { 79 | context.Result = APIResult.参数格式不正确.SetMessage($"参数格式不正确:{value.Errors.First().ErrorMessage}"); 80 | return; 81 | } 82 | } 83 | } 84 | 85 | public override void OnActionExecuted(ActionExecutedContext context) 86 | { 87 | if (context.Result is APIResult apiReturn) 88 | { 89 | var response = JsonSerializer.Serialize(apiReturn); 90 | _ = GetService().Add( 91 | new M_Accesslog 92 | { 93 | Resource = resource?.Content, 94 | Code = apiReturn.Code, 95 | ReqContent = GetRequestBody(context.HttpContext), 96 | UserId = loginUser?.Id, 97 | Remark = resource?.Name, 98 | ResourceId = resource?.Id, 99 | ResContent = response, 100 | IP = IP, 101 | CreateTime = DateTime.Now 102 | }); 103 | } 104 | } 105 | 106 | private string GetRequestBody(HttpContext context) 107 | { 108 | string body = string.Empty; 109 | if (context.Items?.ContainsKey("this_body") == true) 110 | try { body = context.Items["this_body"].ToString(); } catch { } 111 | return body; 112 | } 113 | } 114 | } -------------------------------------------------------------------------------- /examples/IdentityHost/Controllers/PasswordController.cs: -------------------------------------------------------------------------------- 1 | using IdentityHost.Helpers; 2 | using IdentityHost.Services; 3 | using IdentityHost.ViewModel; 4 | using Microsoft.AspNetCore.Mvc; 5 | using Microsoft.Extensions.Configuration; 6 | using Microsoft.Extensions.Logging; 7 | using StackExchange.Redis; 8 | using System.Collections.Generic; 9 | using System.Threading.Tasks; 10 | 11 | namespace IdentityHost.Controllers 12 | { 13 | [Route("password"), ApiExplorerSettings(GroupName = "个人中心")] 14 | public class PasswordController : BaseController 15 | { 16 | private readonly UserService userService; 17 | public PasswordController(IConfiguration cfg, ILogger logger, IEnumerable managerServices, ConnectionMultiplexer multiplexer) : base(cfg, logger, managerServices, multiplexer) 18 | { 19 | userService = GetService(); 20 | } 21 | 22 | /// 23 | /// 修改密码 24 | /// 25 | /// 26 | /// 调用成功自动清除登录信息 27 | /// 28 | /// 29 | /// 30 | [HttpPost("edit")] 31 | public async Task Edit([FromBody] PasswordViewModel model) 32 | { 33 | var password = SecurityHelper.GetSHA256SignString(model.OldPassword); 34 | if (LoginUser.Password != password) 35 | return APIResult.失败.SetMessage("旧密码错误"); 36 | 37 | var result = userService.UpdatePassword(LoginUser.Id, model.NewPassword); 38 | 39 | if (!string.IsNullOrEmpty(base.Token)) 40 | { 41 | await redisClient.GetDatabase().KeyDeleteAsync(SignInKey + Token); 42 | } 43 | 44 | return result ? APIResult.成功 : APIResult.失败; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /examples/IdentityHost/Controllers/R2RController.cs: -------------------------------------------------------------------------------- 1 | using IdentityHost.Services; 2 | using IdentityHost.ViewModel; 3 | using Microsoft.AspNetCore.Mvc; 4 | using Microsoft.Extensions.Configuration; 5 | using Microsoft.Extensions.Logging; 6 | using StackExchange.Redis; 7 | using System.Collections.Generic; 8 | 9 | namespace IdentityHost.Controllers 10 | { 11 | /// 12 | /// Role 2 Resource 13 | /// 14 | [Route("admin/r2r"), ApiExplorerSettings(GroupName = "管理员")] 15 | public class R2RController : BaseController 16 | { 17 | private readonly RoleService roleService; 18 | public R2RController(IConfiguration cfg, ILogger logger, IEnumerable managerServices, ConnectionMultiplexer multiplexer) : base(cfg, logger, managerServices, multiplexer) 19 | { 20 | roleService = GetService(); 21 | } 22 | 23 | /// 24 | /// 添加角色资源权限 25 | /// 26 | /// 27 | /// 28 | [HttpPost("add")] 29 | public IActionResult Add([FromBody] R2RViewModel model) 30 | { 31 | var role = roleService.Detail(model.RoleId); 32 | if (role == null) 33 | return APIResult.记录不存在; 34 | 35 | var result = roleService.AddR2R(model.RoleId, model.ResourceId.ToArray()); 36 | return result ? APIResult.成功 : APIResult.失败; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /examples/IdentityHost/Controllers/R2UController.cs: -------------------------------------------------------------------------------- 1 | using IdentityHost.Services; 2 | using IdentityHost.ViewModel; 3 | using Microsoft.AspNetCore.Mvc; 4 | using Microsoft.Extensions.Configuration; 5 | using Microsoft.Extensions.Logging; 6 | using StackExchange.Redis; 7 | using System.Collections.Generic; 8 | 9 | namespace IdentityHost.Controllers 10 | { 11 | /// 12 | /// Role 2 User 13 | /// 14 | [Route("admin/r2e"), ApiExplorerSettings(GroupName = "管理员")] 15 | public class R2UController : BaseController 16 | { 17 | private readonly UserService userService; 18 | private readonly RoleService roleService; 19 | public R2UController(IConfiguration cfg, ILogger logger, IEnumerable managerServices, ConnectionMultiplexer multiplexer) : base(cfg, logger, managerServices, multiplexer) 20 | { 21 | userService = GetService(); 22 | roleService = GetService(); 23 | } 24 | 25 | /// 26 | /// 添加授权 27 | /// 28 | /// 29 | /// 30 | /// data:{ 31 | /// id: 32 | /// } 33 | /// 34 | /// 35 | /// 36 | /// 37 | [HttpPost("add")] 38 | public IActionResult Add([FromBody] R2UViewModel model) 39 | { 40 | var user = userService.Detail(model.UserId); 41 | if (user == null && user.State != 3) 42 | return APIResult.记录不存在; 43 | 44 | var result = roleService.AddR2U(user.Id, model.RoleId.ToArray()); 45 | 46 | return result ? APIResult.成功 : APIResult.失败; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /examples/IdentityHost/Controllers/RoleController.cs: -------------------------------------------------------------------------------- 1 | using IdentityHost.Model; 2 | using IdentityHost.Services; 3 | using IdentityHost.ViewModel; 4 | using Microsoft.AspNetCore.Mvc; 5 | using Microsoft.Extensions.Configuration; 6 | using Microsoft.Extensions.Logging; 7 | using StackExchange.Redis; 8 | using System.Collections.Generic; 9 | using System.Linq; 10 | 11 | namespace IdentityHost.Controllers 12 | { 13 | [Route("admin/role"), ApiExplorerSettings(GroupName = "管理员")] 14 | public class RoleController : BaseController 15 | { 16 | private readonly RoleService roleService; 17 | private readonly ResourceService resourceService; 18 | public RoleController(IConfiguration cfg, ILogger logger, IEnumerable managerServices, ConnectionMultiplexer multiplexer) : base(cfg, logger, managerServices, multiplexer) 19 | { 20 | roleService = GetService(); 21 | resourceService = GetService(); 22 | } 23 | 24 | /// 25 | /// 添加角色 26 | /// 27 | /// 28 | /// 29 | /// data:{ 30 | /// id: 31 | /// } 32 | /// 33 | /// 34 | /// 35 | /// 36 | [HttpPost("add")] 37 | public IActionResult Add([FromBody] AddRoleViewModel model) 38 | { 39 | var role = roleService.Add(new M_Role { Name = model.Name }); 40 | 41 | return APIResult.成功.SetData("id", role.Id); 42 | } 43 | 44 | /// 45 | /// 编辑角色 46 | /// 47 | /// 48 | /// 49 | /// data:{ 50 | /// id: 51 | /// } 52 | /// 53 | /// 54 | /// 55 | /// 56 | [HttpPost("edit")] 57 | public IActionResult Edit([FromBody] EditRoleViewModel model) 58 | { 59 | var role = roleService.Detail(model.Id); 60 | if (role == null) 61 | return APIResult.记录不存在; 62 | 63 | role = roleService.EditName(role.Id, model.Name); 64 | 65 | return APIResult.成功.SetData("id", role.Id); 66 | } 67 | 68 | /// 69 | /// 删除角色 70 | /// 71 | /// 72 | /// 73 | [HttpPost("delete")] 74 | public IActionResult Delete([FromBody] IdViewModel model) 75 | { 76 | var role = roleService.Detail(model.Id); 77 | if (role == null) 78 | return APIResult.记录不存在; 79 | 80 | var success = roleService.Delete(role.Id); 81 | 82 | return success ? APIResult.成功 : APIResult.失败; 83 | } 84 | 85 | /// 86 | /// 角色详情 87 | /// 88 | /// 89 | /// 90 | /// data:[ 91 | /// role:{ 92 | /// id: 93 | /// name: 名称 94 | /// }, 95 | /// resources:[{ 96 | /// id: 97 | /// parent_id: 98 | /// name: 99 | /// resource: 100 | /// }]] 101 | /// 102 | /// 103 | /// 104 | /// 105 | [HttpPost("detail")] 106 | public IActionResult Detail([FromBody] IdViewModel model) 107 | { 108 | var role = roleService.Detail(model.Id); 109 | if (role == null) 110 | return APIResult.记录不存在; 111 | 112 | var resources = resourceService.ResourceByRole(role.Id); 113 | 114 | return APIResult.成功.SetData("role", new 115 | { 116 | role.Id, 117 | role.Name 118 | }, "resources", resources.Select(f => new 119 | { 120 | f.Id, 121 | f.ParentId, 122 | f.Name, 123 | f.Content 124 | })); 125 | } 126 | 127 | /// 128 | /// 角色列表 129 | /// 130 | /// 131 | /// 132 | /// data:[{ 133 | /// id: 134 | /// name: 名称 135 | /// }] 136 | /// 137 | /// 138 | /// 139 | /// 140 | [HttpPost("list")] 141 | public IActionResult List([FromBody] PageViewModel model) 142 | { 143 | var list = roleService.List(model.PageIndex, model.PageSize); 144 | 145 | return APIResult.成功.SetData("list", list.Select(f => new 146 | { 147 | f.Id, 148 | f.Name 149 | })); 150 | } 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /examples/IdentityHost/Converters/JsonBooleanConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text.Json; 5 | using System.Text.Json.Serialization; 6 | using System.Threading.Tasks; 7 | 8 | namespace IdentityHost.Converters 9 | { 10 | public class JsonBooleanConverter : JsonConverter 11 | { 12 | public override bool Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) 13 | { 14 | return reader.GetBoolean(); 15 | } 16 | public override void Write(Utf8JsonWriter writer, bool value, JsonSerializerOptions options) 17 | { 18 | uint reValue = Convert.ToUInt32(Convert.ToBoolean(value)); 19 | writer.WriteNumberValue(reValue); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /examples/IdentityHost/Converters/JsonLowerCaseNamingPolicy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text.Json; 5 | using System.Threading.Tasks; 6 | 7 | namespace IdentityHost.Converters 8 | { 9 | public class JsonLowerCaseNamingPolicy : JsonNamingPolicy 10 | { 11 | public override string ConvertName(string name) => name.ToLower(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/IdentityHost/Converters/JsonUnixTimeConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text.Json; 5 | using System.Text.Json.Serialization; 6 | using System.Threading.Tasks; 7 | 8 | namespace IdentityHost.Converters 9 | { 10 | public class JsonUnixTimeConverter : JsonConverter 11 | { 12 | private static DateTime Greenwich_Mean_Time = TimeZoneInfo.ConvertTime(new DateTime(1970, 1, 1), TimeZoneInfo.Local); 13 | private const int Limit = 10000; 14 | 15 | public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) 16 | { 17 | if (reader.TokenType == JsonTokenType.Number) 18 | { 19 | var unixTime = reader.GetInt64(); 20 | var dt = new DateTime(Greenwich_Mean_Time.Ticks + unixTime * Limit); 21 | return dt; 22 | } 23 | else 24 | { 25 | return reader.GetDateTime(); 26 | } 27 | } 28 | public override void Write(Utf8JsonWriter writer, DateTime dateTime, JsonSerializerOptions options) 29 | { 30 | var unixTime = (dateTime - Greenwich_Mean_Time).Ticks / Limit; 31 | writer.WriteNumberValue(unixTime); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /examples/IdentityHost/Extensions/CustomerAuthorizeFilter.cs: -------------------------------------------------------------------------------- 1 | using IdentityHost.Model; 2 | using IdentityHost.Services; 3 | using Microsoft.AspNetCore.Authorization; 4 | using Microsoft.AspNetCore.Authorization.Infrastructure; 5 | using Microsoft.AspNetCore.Hosting; 6 | using Microsoft.AspNetCore.Http; 7 | using Microsoft.AspNetCore.Mvc.Authorization; 8 | using Microsoft.AspNetCore.Mvc.Filters; 9 | using Microsoft.Extensions.Hosting; 10 | using StackExchange.Redis; 11 | using System; 12 | using System.Collections.Generic; 13 | using System.Linq; 14 | using System.Threading.Tasks; 15 | using LocalResource = IdentityHost.Properties.Resource; 16 | 17 | namespace IdentityHost.Extensions 18 | { 19 | public class CustomerAuthorizeFilter : AuthorizeFilter 20 | { 21 | protected const string SignInKey = "SignInKey_"; 22 | private static readonly AuthorizationPolicy _policy_ = new AuthorizationPolicy(new[] { new DenyAnonymousAuthorizationRequirement() }, new string[] { }); 23 | private M_Resource resource; 24 | private int userId; 25 | private readonly RoleService roleService; 26 | private readonly ResourceService resourceService; 27 | private readonly AccessLogService accessLogService; 28 | private readonly ConnectionMultiplexer redisClient; 29 | 30 | public CustomerAuthorizeFilter(IEnumerable managerServices, ConnectionMultiplexer multiplexer) : base(_policy_) 31 | { 32 | roleService = GetService(managerServices); 33 | resourceService = GetService(managerServices); 34 | accessLogService = GetService(managerServices); 35 | redisClient = multiplexer; 36 | } 37 | 38 | public T GetService(IEnumerable managerServices) => (T)managerServices.FirstOrDefault(f => f.ServiceName == typeof(T).Name); 39 | 40 | public override async Task OnAuthorizationAsync(AuthorizationFilterContext context) 41 | { 42 | var env = (IWebHostEnvironment)context.HttpContext.RequestServices.GetService(typeof(IWebHostEnvironment)); 43 | if (env.EnvironmentName == Environments.Development) // 测试环境不予以校验 44 | { 45 | return; 46 | } 47 | else 48 | { 49 | var ctx = context.HttpContext; 50 | var path = ctx.Request.Path.Value; 51 | var result = await CheckResource(ctx, path); 52 | if (result.Code != 0) 53 | { 54 | context.Result = result; 55 | } 56 | AddAccessLog(result, context.HttpContext); 57 | } 58 | } 59 | 60 | private async Task CheckResource(HttpContext ctx, string path) 61 | { 62 | resource = resourceService.Detail(path); 63 | if (resource == null) 64 | return APIResult.失败.SetMessage(LocalResource.NotFound); 65 | 66 | if (resource.Authorize) 67 | { 68 | var token = ctx.Request.Headers["token"]; 69 | if (string.IsNullOrEmpty(token)) 70 | return APIResult.用户_未登录; 71 | 72 | int.TryParse(await redisClient.GetDatabase().StringGetAsync(SignInKey + token), out userId); 73 | var roleId = roleService.GetRoles(userId).Select(f => f.Id).ToList(); 74 | if (roleId.Count == 0) 75 | return APIResult.没有访问权限; 76 | else 77 | { 78 | var access = roleService.ValidatorRole(resource.Id, roleId.ToArray()); 79 | if (!access) 80 | return APIResult.没有访问权限; 81 | } 82 | } 83 | 84 | return APIResult.成功; 85 | } 86 | 87 | private void AddAccessLog(APIResult apiReturn, HttpContext context) 88 | { 89 | var resourceName = resource == null ? context.Request.Path.Value : resource.Content; 90 | _ = accessLogService.Add(new M_Accesslog 91 | { 92 | Resource = resourceName, 93 | Code = apiReturn.Code, 94 | ReqContent = GetRequestBody(context), 95 | UserId = userId, 96 | Remark = resource?.Name, 97 | ResourceId = resource?.Id, 98 | ResContent = null, 99 | IP = GetClientIP(context), 100 | CreateTime = DateTime.Now, 101 | }); 102 | } 103 | 104 | private string GetRequestBody(HttpContext context) 105 | { 106 | string body = string.Empty; 107 | if (context.Items?.ContainsKey("this_body") == true) 108 | try { body = context.Items["this_body"].ToString(); } catch { } 109 | return body; 110 | } 111 | 112 | public string GetClientIP(HttpContext context) 113 | { 114 | return context.Request.Headers["X-Real-IP"].FirstOrDefault() ?? context.Request.HttpContext.Connection.RemoteIpAddress?.ToString(); 115 | } 116 | 117 | } 118 | } -------------------------------------------------------------------------------- /examples/IdentityHost/Extensions/CustomerExceptionFilter.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using Microsoft.AspNetCore.Mvc.Filters; 3 | using Microsoft.Extensions.Hosting; 4 | using Microsoft.Extensions.Logging; 5 | using System; 6 | using System.Text.Json; 7 | 8 | namespace IdentityHost.Extensions 9 | { 10 | public class CustomerExceptionFilter : ExceptionFilterAttribute 11 | { 12 | private readonly ILogger _logger = null; 13 | private readonly IWebHostEnvironment _env = null; 14 | 15 | 16 | public CustomerExceptionFilter(ILogger logger,IWebHostEnvironment env) 17 | { 18 | _logger = logger; 19 | _env = env; 20 | } 21 | 22 | public override void OnException(ExceptionContext context) 23 | { 24 | if (context.Exception is OperationCanceledException) 25 | { 26 | _logger.LogInformation("Request was cancelled"); 27 | context.ExceptionHandled = true; 28 | return; 29 | } 30 | if (context.Exception is APIReturnException ar) 31 | { 32 | context.Result = new APIResult(ar.HResult, ar.Message); 33 | return; 34 | } 35 | string exmessage = string.Empty; 36 | void act(Exception ex) 37 | { 38 | exmessage += string.Format("{0} {1} {2} {3}", 39 | ex, 40 | ex.StackTrace, 41 | ex.InnerException, 42 | ex.Message, 43 | ex.Data == null ? null : JsonSerializer.Serialize(ex.Data) 44 | ); 45 | if (ex.InnerException != null) 46 | { 47 | act(ex.InnerException); 48 | } 49 | } 50 | 51 | act(context.Exception); 52 | _logger.LogError(exmessage); 53 | 54 | if (_env.IsDevelopment() || _env.IsStaging()) 55 | { 56 | context.Result = APIResult.失败.SetMessage(context.Exception.Message); 57 | } 58 | else 59 | { 60 | context.Result = APIResult.系统内置_内部异常; 61 | } 62 | context.ExceptionHandled = true; 63 | } 64 | 65 | } 66 | 67 | public partial class APIReturnException : Exception 68 | { 69 | public APIReturnException(int code, string message) : base(message) 70 | { 71 | HResult = code; 72 | } 73 | public APIReturnException(APIResult ar) : base(ar.Message) 74 | { 75 | HResult = ar.Code; 76 | 77 | } 78 | public static implicit operator APIReturnException(APIResult value) 79 | { 80 | return new APIReturnException(value); 81 | } 82 | public static implicit operator APIResult(APIReturnException value) 83 | { 84 | return new APIResult(value.HResult, value.Message); 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /examples/IdentityHost/Extensions/JsonSerializerExtension.cs: -------------------------------------------------------------------------------- 1 | using IdentityHost.Converters; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text.Encodings.Web; 6 | using System.Text.Json; 7 | using System.Text.Json.Serialization; 8 | using System.Text.Unicode; 9 | using System.Threading.Tasks; 10 | 11 | namespace IdentityHost.Extensions 12 | { 13 | public class JsonSerializerExtension 14 | { 15 | public static JsonSerializerOptions JsonOptions 16 | { 17 | get 18 | { 19 | var options = new JsonSerializerOptions(); 20 | options.Converters.Add(new JsonBooleanConverter()); 21 | options.Converters.Add(new JsonUnixTimeConverter()); 22 | options.Converters.Add(new JsonStringEnumConverter()); 23 | options.PropertyNamingPolicy = new JsonLowerCaseNamingPolicy(); 24 | options.PropertyNameCaseInsensitive = true; 25 | options.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All); 26 | return options; 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /examples/IdentityHost/Extensions/RequestMiddleware.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | using Microsoft.Extensions.Logging; 3 | using System; 4 | using System.Buffers; 5 | using System.IO.Pipelines; 6 | using System.Text; 7 | using System.Text.Json; 8 | using System.Threading.Tasks; 9 | 10 | namespace IdentityHost.Extensions 11 | { 12 | public class RequestMiddleware 13 | { 14 | private readonly RequestDelegate _next; 15 | private readonly ILogger _logger; 16 | public RequestMiddleware(RequestDelegate next, ILogger logger) 17 | { 18 | _next = next; 19 | _logger = logger; 20 | } 21 | 22 | public async Task Invoke(HttpContext context) 23 | { 24 | context.Request.EnableBuffering(); 25 | if (context.Request.ContentType?.Contains("multipart/form-data; boundary=") == true) 26 | { 27 | var fileName = context.Request.Form?.Files[0]?.FileName; 28 | context.Items.Add("this_body", JsonSerializer.Serialize(new { file = fileName ?? "file" })); 29 | } 30 | else 31 | { 32 | var str = await GetContextRequestBody(context.Request.BodyReader); 33 | if (context.Items?.ContainsKey("this_body") != true && !string.IsNullOrEmpty(str)) 34 | context.Items.Add("this_body", str); 35 | } 36 | try 37 | { 38 | context.Request.Body.Position = 0; 39 | await _next.Invoke(context); 40 | } 41 | catch (InvalidOperationException ioe) 42 | { 43 | _logger.LogError("中间件下一步命令报错"); 44 | throw ioe; 45 | } 46 | } 47 | 48 | private async Task GetContextRequestBody(PipeReader reader) 49 | { 50 | ReadResult readResult; 51 | try 52 | { 53 | readResult = await reader.ReadAsync(); 54 | } 55 | catch (Exception ex) 56 | { 57 | _logger.LogError(ex, "readasync error,{Message}", ex.Message); 58 | throw; 59 | } 60 | 61 | var buffer = readResult.Buffer; 62 | if (buffer.Length <= 0) 63 | { 64 | reader.AdvanceTo(buffer.Start); 65 | return "{}"; 66 | } 67 | var resturnStr = GetBufferString(buffer); 68 | try 69 | { 70 | reader.AdvanceTo(buffer.Start); 71 | } 72 | catch (Exception ex) 73 | { 74 | ex.Data["segment"] = readResult.Buffer.IsSingleSegment; 75 | ex.Data["start"] = buffer.Start.GetInteger(); 76 | ex.Data["end"] = buffer.End.GetInteger(); 77 | _logger.LogError(ex, "Middleware pipereader error, {Message}", JsonSerializer.Serialize(ex.Data)); 78 | throw; 79 | } 80 | return resturnStr; 81 | } 82 | private static string GetBufferString(in ReadOnlySequence readOnlySequence) 83 | { 84 | ReadOnlySpan span = readOnlySequence.IsSingleSegment ? readOnlySequence.FirstSpan : readOnlySequence.ToArray().AsSpan(); 85 | return Encoding.UTF8.GetString(span); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /examples/IdentityHost/Extensions/StartupExtensions.cs: -------------------------------------------------------------------------------- 1 | using IdentityHost.Services; 2 | using Microsoft.Extensions.Configuration; 3 | using Microsoft.Extensions.DependencyInjection; 4 | using MyStaging.Metadata; 5 | using StackExchange.Redis; 6 | using System.Text.Encodings.Web; 7 | using System.Text.Json; 8 | using System.Text.Unicode; 9 | 10 | namespace IdentityHost.Extensions 11 | { 12 | public static class StartupExtensions 13 | { 14 | public static IServiceCollection AddSingletonSerializerOptions(this IServiceCollection services) 15 | { 16 | services.AddSingleton((s) => 17 | { 18 | var encoderSettings = new TextEncoderSettings(); 19 | encoderSettings.AllowRanges(UnicodeRanges.CjkUnifiedIdeographs, UnicodeRanges.BasicLatin); 20 | var options = new JsonSerializerOptions 21 | { 22 | Encoder = JavaScriptEncoder.Create(encoderSettings) 23 | //Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping 24 | }; 25 | return options; 26 | }); 27 | return services; 28 | } 29 | 30 | public static IServiceCollection AddIManagerService(this IServiceCollection services) 31 | { 32 | services.AddScoped() 33 | .AddScoped() 34 | .AddScoped() 35 | .AddScoped(); 36 | 37 | return services; 38 | } 39 | 40 | public static IServiceCollection AddCustomCors(this IServiceCollection services) 41 | { 42 | services.AddCors(options => options.AddPolicy( 43 | "all", 44 | builder => builder 45 | .AllowAnyHeader() 46 | .AllowAnyMethod() 47 | .AllowAnyOrigin() 48 | )); 49 | 50 | return services; 51 | } 52 | 53 | public static IServiceCollection AddMyStagingDbContenxt(this IServiceCollection services, IConfiguration configuration) 54 | { 55 | var options = new StagingOptions("MySql", configuration["ConnectionStrings:MySql"]); 56 | services.AddScoped(fct => new IdentityHostDbContext(options)); 57 | return services; 58 | } 59 | 60 | public static IServiceCollection AddStackExchangeRedis(this IServiceCollection services, IConfiguration configuration) 61 | { 62 | var multiplexer = ConnectionMultiplexer.Connect(configuration["ConnectionStrings:Redis"]); 63 | services.AddSingleton(multiplexer); 64 | return services; 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /examples/IdentityHost/Extensions/SwaggerExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.DependencyInjection; 4 | using Microsoft.OpenApi.Models; 5 | using System; 6 | using System.IO; 7 | 8 | namespace IdentityHost.Extensions 9 | { 10 | public static class SwashbuckleSwaggerExtensions 11 | { 12 | public static readonly string[] docs = new[] { "首页", "个人中心", "管理员" }; 13 | 14 | public static IServiceCollection AddCustomSwagger(this IServiceCollection services, IWebHostEnvironment env) 15 | { 16 | services.AddSwaggerGen(c => 17 | { 18 | foreach (var doc in docs) 19 | c.SwaggerDoc(doc, new OpenApiInfo 20 | { 21 | Version = doc, 22 | Title = doc 23 | }); 24 | c.EnableAnnotations(); 25 | c.IgnoreObsoleteProperties(); // Obsolete接口划删除线 26 | c.CustomSchemaIds(a => a.FullName); 27 | var basePath = Path.GetDirectoryName(AppContext.BaseDirectory); 28 | var xmlPath = Path.Combine(basePath, $"{env.ApplicationName}.xml"); 29 | c.IncludeXmlComments(xmlPath); // 加载生成XML文件 30 | }); 31 | 32 | return services; 33 | } 34 | 35 | public static IApplicationBuilder UseCustomizedSwagger(this IApplicationBuilder app) 36 | { 37 | app.UseSwaggerUI(c => 38 | { 39 | c.DocExpansion(Swashbuckle.AspNetCore.SwaggerUI.DocExpansion.None); // 默认折叠 40 | foreach (var doc in docs) 41 | c.SwaggerEndpoint($"/swagger/{doc}/swagger.json", doc); 42 | //c.RoutePrefix = string.Empty; 43 | }).UseSwagger(); 44 | return app; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /examples/IdentityHost/Helper/AesFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Security.Cryptography; 4 | using System.Text; 5 | 6 | namespace IdentityHost.Helpers 7 | { 8 | public class AesFactory 9 | { 10 | /// 11 | /// 加密字符串 12 | /// 13 | /// 待加密文本 14 | /// 密钥,长度为32 15 | /// 向量,长度为16 16 | /// 17 | public static byte[] EncryptStringToBytes(string plainText, string key, string iv) 18 | { 19 | if (string.IsNullOrEmpty(plainText)) 20 | throw new ArgumentNullException(nameof(plainText)); 21 | if (string.IsNullOrEmpty(key) || key.Length != 32) 22 | throw new ArgumentOutOfRangeException(nameof(key)); 23 | if (string.IsNullOrEmpty(iv) || iv.Length != 16) 24 | throw new ArgumentOutOfRangeException(nameof(iv)); 25 | 26 | byte[] encrypted; 27 | using (var aes = Aes.Create()) 28 | { 29 | aes.Key = Encoding.UTF8.GetBytes(key); 30 | aes.IV = Encoding.UTF8.GetBytes(iv); 31 | 32 | ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV); 33 | using MemoryStream msEncrypt = new(); 34 | using CryptoStream csEncrypt = new(msEncrypt, encryptor, CryptoStreamMode.Write); 35 | using (StreamWriter swEncrypt = new(csEncrypt)) 36 | { 37 | swEncrypt.Write(plainText); 38 | } 39 | encrypted = msEncrypt.ToArray(); 40 | } 41 | 42 | return encrypted; 43 | } 44 | 45 | /// 46 | /// 解密字符串 47 | /// 48 | /// 待解密数据 49 | /// 密钥,长度为32 50 | /// 向量,长度为16 51 | /// 52 | public static string DecryptStringFromBytes(byte[] cipherData, string key, string iv) 53 | { 54 | if (cipherData == null) 55 | throw new ArgumentNullException(nameof(cipherData)); 56 | if (string.IsNullOrEmpty(key) || key.Length != 32) 57 | throw new ArgumentOutOfRangeException(nameof(key)); 58 | if (string.IsNullOrEmpty(iv) || iv.Length != 16) 59 | throw new ArgumentOutOfRangeException(nameof(iv)); 60 | 61 | string plainText; 62 | using (var aes = Aes.Create()) 63 | { 64 | aes.Key = Encoding.UTF8.GetBytes(key); 65 | aes.IV = Encoding.UTF8.GetBytes(iv); 66 | 67 | ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV); 68 | using MemoryStream msDecrypt = new(cipherData); 69 | using CryptoStream csDecrypt = new(msDecrypt, decryptor, CryptoStreamMode.Read); 70 | using StreamReader srDecrypt = new(csDecrypt); 71 | plainText = srDecrypt.ReadToEnd(); 72 | } 73 | return plainText; 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /examples/IdentityHost/Helper/SecurityHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security.Cryptography; 3 | using System.Text; 4 | 5 | namespace IdentityHost.Helpers 6 | { 7 | public class SecurityHelper 8 | { 9 | public static string GetMD5String(string content) 10 | { 11 | byte[] result = Encoding.UTF8.GetBytes(content); 12 | using (MD5 md5 = MD5.Create()) 13 | { 14 | var md5result = BitConverter.ToString(md5.ComputeHash(result)).Replace("-", ""); 15 | return md5result.ToLower(); 16 | }; 17 | } 18 | 19 | public static string GetSHA1SignString(string content) 20 | { 21 | SHA1 sha1 = SHA1.Create(); 22 | byte[] result = Encoding.UTF8.GetBytes(content); 23 | byte[] sha1result = sha1.ComputeHash(result); 24 | string sha1str = BitConverter.ToString(sha1result).Replace("-", "").ToLower(); 25 | return sha1str; 26 | } 27 | 28 | 29 | public static string GetSHA256SignString(string content) 30 | { 31 | SHA256 sha256 = SHA256.Create(); 32 | byte[] result = Encoding.UTF8.GetBytes(content); 33 | byte[] sha1result = sha256.ComputeHash(result); 34 | string sha1str = BitConverter.ToString(sha1result).Replace("-", "").ToLower(); 35 | return sha1str; 36 | } 37 | 38 | public static string GetStrBySHA1ToBase64(string value) 39 | { 40 | byte[] source = Encoding.UTF8.GetBytes(value); 41 | using (SHA1 sha1 = SHA1.Create()) 42 | { 43 | var crypto = sha1.ComputeHash(source); 44 | var str = Convert.ToBase64String(crypto, Base64FormattingOptions.None); 45 | return str; 46 | } 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /examples/IdentityHost/IdentityHost.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net6.0 5 | 6 | 7 | 8 | D:\MyGitHub\mystaging\examples\IdentityHost\IdentityHost.xml 9 | 1701;1702;1591 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | True 37 | True 38 | Resource.resx 39 | 40 | 41 | 42 | 43 | 44 | ResXFileCodeGenerator 45 | Resource.Designer.cs 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /examples/IdentityHost/IdentityHost.csproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | true 5 | IdentityHost 6 | 7 | 8 | ProjectDebugger 9 | 10 | -------------------------------------------------------------------------------- /examples/IdentityHost/Model/Article.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.DataAnnotations; 2 | using System; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | 5 | namespace IdentityHost.Model 6 | { 7 | [Table(name: "Article", Schema = "mystaging")] 8 | public partial class Article 9 | { 10 | [PrimaryKey(AutoIncrement = true)] 11 | public int Id { get; set; } 12 | [Column(TypeName = "tinyint(1)")] 13 | public bool State { get; set; } 14 | public int UserId { get; set; } 15 | public string Title { get; set; } 16 | public string Content { get; set; } 17 | public DateTime CreateTime { get; set; } 18 | public string IP { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/IdentityHost/Model/Customer.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.DataAnnotations; 2 | using System.ComponentModel.DataAnnotations.Schema; 3 | 4 | namespace IdentityHost.Model 5 | { 6 | [Table(name: "Customer", Schema = "mystaging")] 7 | public partial class Customer 8 | { 9 | [PrimaryKey(AutoIncrement = true)] 10 | public int Id { get; set; } 11 | public string Name { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/IdentityHost/Model/IdentityHostDbContext.cs: -------------------------------------------------------------------------------- 1 | using IdentityHost.Model; 2 | using MyStaging.Core; 3 | using MyStaging.Metadata; 4 | 5 | namespace IdentityHost 6 | { 7 | public partial class IdentityHostDbContext : DbContext 8 | { 9 | public IdentityHostDbContext(StagingOptions options) : base(options, ProviderType.MySql) 10 | { 11 | } 12 | 13 | public DbSet
Article { get; set; } 14 | public DbSet Customer { get; set; } 15 | public DbSet M_Accesslog { get; set; } 16 | public DbSet M_Mapping { get; set; } 17 | public DbSet M_Resource { get; set; } 18 | public DbSet M_Role { get; set; } 19 | public DbSet M_Roleresource { get; set; } 20 | public DbSet M_User { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /examples/IdentityHost/Model/M_Accesslog.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.DataAnnotations; 2 | using System; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | 5 | namespace IdentityHost.Model 6 | { 7 | [Table(name: "M_Accesslog", Schema = "mystaging")] 8 | public partial class M_Accesslog 9 | { 10 | [PrimaryKey(AutoIncrement = true)] 11 | public int Id { get; set; } 12 | /// 13 | /// 用户编号 14 | /// 15 | public int? UserId { get; set; } 16 | /// 17 | /// 资源内容 18 | /// 19 | public string Resource { get; set; } 20 | /// 21 | /// 资源编号 22 | /// 23 | public int? ResourceId { get; set; } 24 | /// 25 | /// 请求内容 26 | /// 27 | [Column(TypeName = "text")] 28 | public string ReqContent { get; set; } 29 | /// 30 | /// 响应内容 31 | /// 32 | [Column(TypeName = "text")] 33 | public string ResContent { get; set; } 34 | /// 35 | /// 客户端IP地址 36 | /// 37 | public string IP { get; set; } 38 | /// 39 | /// 响应代码 40 | /// 41 | public int? Code { get; set; } 42 | /// 43 | /// 备注 44 | /// 45 | public string Remark { get; set; } 46 | /// 47 | /// 创建时间 48 | /// 49 | public DateTime CreateTime { get; set; } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /examples/IdentityHost/Model/M_Mapping.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.DataAnnotations; 2 | using System; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | 5 | namespace IdentityHost.Model 6 | { 7 | [Table(name: "M_Mapping", Schema = "mystaging")] 8 | public partial class M_Mapping 9 | { 10 | /// 11 | /// 用户编号 12 | /// 13 | [PrimaryKey] 14 | public int UserId { get; set; } 15 | /// 16 | /// 角色编号 17 | /// 18 | [PrimaryKey] 19 | public int RoleId { get; set; } 20 | /// 21 | /// 创建时间 22 | /// 23 | public DateTime CreateTime { get; set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /examples/IdentityHost/Model/M_Resource.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.DataAnnotations; 2 | using System; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | 5 | namespace IdentityHost.Model 6 | { 7 | [Table(name: "M_Resource", Schema = "mystaging")] 8 | public partial class M_Resource 9 | { 10 | [PrimaryKey(AutoIncrement = true)] 11 | public int Id { get; set; } 12 | /// 13 | /// 上级编号 14 | /// 15 | public int? ParentId { get; set; } 16 | /// 17 | /// 资源名称 18 | /// 19 | public string Name { get; set; } 20 | /// 21 | /// 资源内容 22 | /// 23 | public string Content { get; set; } 24 | /// 25 | /// 资源类型,0=API,1=网页元素 26 | /// 27 | public int Type { get; set; } 28 | /// 29 | /// 状态,0=正常,1=冻结,2=删除 30 | /// 31 | public int State { get; set; } 32 | /// 33 | /// 是否需要授权访问 34 | /// 35 | [Column(TypeName = "tinyint(1)")] 36 | public bool Authorize { get; set; } 37 | /// 38 | /// 排序号,按数字顺序排序 39 | /// 40 | public int Sort { get; set; } 41 | /// 42 | /// 创建时间 43 | /// 44 | public DateTime CreateTime { get; set; } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /examples/IdentityHost/Model/M_Role.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.DataAnnotations; 2 | using System; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | 6 | namespace IdentityHost.Model 7 | { 8 | [Table(name: "M_Role", Schema = "mystaging")] 9 | public partial class M_Role 10 | { 11 | /// 12 | /// 编号 13 | /// 14 | [PrimaryKey(AutoIncrement = true)] 15 | public int Id { get; set; } 16 | /// 17 | /// 名称 18 | /// 19 | [Required] 20 | public string Name { get; set; } 21 | /// 22 | /// 状态,0=正常,1=冻结,2=删除 23 | /// 24 | public int State { get; set; } 25 | /// 26 | /// 创建时间 27 | /// 28 | public DateTime CreateTime { get; set; } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /examples/IdentityHost/Model/M_Roleresource.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.DataAnnotations; 2 | using System.ComponentModel.DataAnnotations.Schema; 3 | 4 | namespace IdentityHost.Model 5 | { 6 | [Table(name: "M_Roleresource", Schema = "mystaging")] 7 | public partial class M_Roleresource 8 | { 9 | /// 10 | /// 角色编号 11 | /// 12 | [PrimaryKey] 13 | public int RoleId { get; set; } 14 | /// 15 | /// 资源编号 16 | /// 17 | [PrimaryKey] 18 | public int ResourceId { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/IdentityHost/Model/M_User.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.DataAnnotations; 2 | using System; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | 6 | namespace IdentityHost.Model 7 | { 8 | [Table(name: "M_User", Schema = "mystaging")] 9 | public partial class M_User 10 | { 11 | /// 12 | /// 编号 13 | /// 14 | [PrimaryKey(AutoIncrement = true)] 15 | public int Id { get; set; } 16 | /// 17 | /// 头像 18 | /// 19 | [Column(TypeName = "varchar(700)")] 20 | public string ImgFace { get; set; } 21 | /// 22 | /// 姓名 23 | /// 24 | [Required] 25 | public string Name { get; set; } 26 | /// 27 | /// 手机号码 28 | /// 29 | [Column(TypeName = "varchar(11)")] 30 | public string Phone { get; set; } 31 | /// 32 | /// 登录名 33 | /// 34 | [Required] 35 | public string LoginName { get; set; } 36 | /// 37 | /// 登录密码 38 | /// 39 | [Required] 40 | public string Password { get; set; } 41 | /// 42 | /// 状态,0=正常,1=未激活,2=冻结,3=删除 43 | /// 44 | public int State { get; set; } 45 | /// 46 | /// 创建时间 47 | /// 48 | public DateTime CreateTime { get; set; } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /examples/IdentityHost/Program.cs: -------------------------------------------------------------------------------- 1 | using IdentityHost.Extensions; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.Hosting; 4 | using System; 5 | using System.Text.Json; 6 | 7 | namespace IdentityHost 8 | { 9 | public class Program 10 | { 11 | public static void Main(string[] args) 12 | { 13 | CreateHostBuilder(args).Build().Run(); 14 | } 15 | 16 | public static IHostBuilder CreateHostBuilder(string[] args) => 17 | Host.CreateDefaultBuilder(args) 18 | .ConfigureWebHostDefaults(webBuilder => 19 | { 20 | webBuilder.UseStartup(); 21 | }); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/IdentityHost/Properties/Resource.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // 此代码由工具生成。 4 | // 运行时版本:4.0.30319.42000 5 | // 6 | // 对此文件的更改可能会导致不正确的行为,并且如果 7 | // 重新生成代码,这些更改将会丢失。 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace IdentityHost.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// 一个强类型的资源类,用于查找本地化的字符串等。 17 | /// 18 | // 此类是由 StronglyTypedResourceBuilder 19 | // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 20 | // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen 21 | // (以 /str 作为命令选项),或重新生成 VS 项目。 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resource { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resource() { 33 | } 34 | 35 | /// 36 | /// 返回此类使用的缓存的 ResourceManager 实例。 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("IdentityHost.Properties.Resource", typeof(Resource).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// 重写当前线程的 CurrentUICulture 属性 51 | /// 重写当前线程的 CurrentUICulture 属性。 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// 查找类似 记录已经存在:{0} 的本地化字符串。 65 | /// 66 | internal static string AlreadyExists { 67 | get { 68 | return ResourceManager.GetString("AlreadyExists", resourceCulture); 69 | } 70 | } 71 | 72 | /// 73 | /// 查找类似 文件不合法 的本地化字符串。 74 | /// 75 | internal static string FileInvalid { 76 | get { 77 | return ResourceManager.GetString("FileInvalid", resourceCulture); 78 | } 79 | } 80 | 81 | /// 82 | /// 查找类似 资源不存在 的本地化字符串。 83 | /// 84 | internal static string NotFound { 85 | get { 86 | return ResourceManager.GetString("NotFound", resourceCulture); 87 | } 88 | } 89 | 90 | /// 91 | /// 查找类似 不支持多级分类 的本地化字符串。 92 | /// 93 | internal static string NotSupport { 94 | get { 95 | return ResourceManager.GetString("NotSupport", resourceCulture); 96 | } 97 | } 98 | 99 | /// 100 | /// 查找类似 上级分类不存在 的本地化字符串。 101 | /// 102 | internal static string ParentNotFound { 103 | get { 104 | return ResourceManager.GetString("ParentNotFound", resourceCulture); 105 | } 106 | } 107 | 108 | /// 109 | /// 查找类似 重复的操作 的本地化字符串。 110 | /// 111 | internal static string Repeat { 112 | get { 113 | return ResourceManager.GetString("Repeat", resourceCulture); 114 | } 115 | } 116 | 117 | /// 118 | /// 查找类似 测试 的本地化字符串。 119 | /// 120 | internal static string Test { 121 | get { 122 | return ResourceManager.GetString("Test", resourceCulture); 123 | } 124 | } 125 | 126 | /// 127 | /// 查找类似 生效时间必须大于当前时间 的本地化字符串。 128 | /// 129 | internal static string TimeTooEarly { 130 | get { 131 | return ResourceManager.GetString("TimeTooEarly", resourceCulture); 132 | } 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /examples/IdentityHost/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:62268", 8 | "sslPort": 0 9 | } 10 | }, 11 | "profiles": { 12 | "IIS Express": { 13 | "commandName": "IISExpress", 14 | "launchBrowser": true, 15 | "launchUrl": "swagger", 16 | "environmentVariables": { 17 | "ASPNETCORE_ENVIRONMENT": "Development" 18 | } 19 | }, 20 | "IdentityHost": { 21 | "commandName": "Project", 22 | "launchBrowser": true, 23 | "launchUrl": "swagger", 24 | "applicationUrl": "http://localhost:5000", 25 | "environmentVariables": { 26 | "ASPNETCORE_ENVIRONMENT": "Development" 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /examples/IdentityHost/Services/AccessLogService.cs: -------------------------------------------------------------------------------- 1 | using IdentityHost.Model; 2 | using System.Collections.Generic; 3 | 4 | namespace IdentityHost.Services 5 | { 6 | public class AccessLogService : IManagerService 7 | { 8 | private readonly IdentityHostDbContext dbContext; 9 | public AccessLogService(IdentityHostDbContext dbContext) 10 | { 11 | this.dbContext = dbContext; 12 | } 13 | 14 | public string ServiceName => nameof(AccessLogService); 15 | 16 | public M_Accesslog Add(M_Accesslog accesslog) 17 | { 18 | return dbContext.M_Accesslog.Insert.Add(accesslog); 19 | } 20 | 21 | public M_Accesslog Detail(int id) 22 | { 23 | var log = dbContext.M_Accesslog.Select.Where(f => f.Id == id).ToOne(); 24 | 25 | return log; 26 | } 27 | 28 | public List List(int pageIndex, int pageSize) 29 | { 30 | var builder = dbContext.M_Accesslog.Select.Page(pageIndex, pageSize).OrderByDescing(f => f.CreateTime); 31 | 32 | return builder.ToList(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /examples/IdentityHost/Services/IManagerService.cs: -------------------------------------------------------------------------------- 1 | namespace IdentityHost.Services 2 | { 3 | public interface IManagerService 4 | { 5 | string ServiceName { get; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /examples/IdentityHost/Services/RoleService.cs: -------------------------------------------------------------------------------- 1 | using IdentityHost.Model; 2 | using MyStaging.Function; 3 | using System; 4 | using System.Collections.Generic; 5 | 6 | namespace IdentityHost.Services 7 | { 8 | public class RoleService : IManagerService 9 | { 10 | private readonly IdentityHostDbContext dbContext; 11 | public RoleService(IdentityHostDbContext dbContext) 12 | { 13 | this.dbContext = dbContext; 14 | } 15 | 16 | public string ServiceName => nameof(RoleService); 17 | 18 | public M_Role Add(M_Role role) 19 | { 20 | role.CreateTime = DateTime.Now; 21 | role.State = 0; 22 | return dbContext.M_Role.Insert.Add(role); 23 | } 24 | 25 | public M_Role EditName(int id, string name) 26 | { 27 | var role = dbContext.M_Role.Update.SetValue(f => f.Name, name).Where(f => f.Id == id).SaveChange(); 28 | return role; 29 | } 30 | 31 | public bool Delete(int id) 32 | { 33 | var affrows = dbContext.M_Role.Delete.Where(f => f.Id == id).SaveChange(); 34 | affrows += dbContext.M_Mapping.Delete.Where(f => f.RoleId == id).SaveChange(); 35 | return affrows > 0; 36 | } 37 | 38 | public M_Role Detail(int id) 39 | { 40 | return dbContext.M_Role.Select.Where(f => f.Id == id).ToOne(); 41 | } 42 | 43 | public List List(int pageIndex, int pageSize) 44 | { 45 | var results = dbContext.M_Role.Select.Page(pageIndex, pageSize).OrderByDescing(f => f.CreateTime).ToList(); 46 | 47 | return results; 48 | } 49 | 50 | public List GetRoles(int userId) 51 | { 52 | var roles = dbContext.M_Mapping.Select.InnerJoin("b", (a, b) => a.RoleId == b.Id && b.State == 0) 53 | .Where(f => f.UserId == userId) 54 | .OrderBy(f => f.CreateTime) 55 | .ToList("b.Id,b.Name"); 56 | return roles; 57 | } 58 | 59 | public bool AddR2U(int userId, int[] roleId) 60 | { 61 | var affrows = 0; 62 | if (roleId?.Length > 0) 63 | { 64 | var roles = dbContext.M_Role.Select.Where(f => f.Id.In(roleId)).ToList(); 65 | if (roles.Count == 0) 66 | throw new ArgumentException(); 67 | 68 | var insertItem = new List(); 69 | foreach (var item in roles) 70 | { 71 | var roleItem = new M_Mapping 72 | { 73 | UserId = userId, 74 | RoleId = item.Id 75 | }; 76 | 77 | insertItem.Add(roleItem); 78 | } 79 | 80 | affrows = dbContext.M_Mapping.Delete.Where(f => f.UserId == userId).SaveChange(); 81 | affrows += dbContext.M_Mapping.Insert.AddRange(insertItem).SaveChange(); 82 | } 83 | else 84 | { 85 | affrows = dbContext.M_Mapping.Delete.Where(f => f.UserId == userId).SaveChange(); 86 | } 87 | 88 | return affrows > 0; 89 | } 90 | 91 | public bool AddR2R(int roleId, int[] resourceId) 92 | { 93 | var affrows = 0; 94 | 95 | if (resourceId?.Length > 0) 96 | { 97 | var res = dbContext.M_Resource.Select.Where(f => f.Id.In(resourceId)).ToList(); 98 | if (res.Count == 0) 99 | throw new ArgumentException(); 100 | 101 | var resources = new List(); 102 | foreach (var item in res) 103 | { 104 | var roleresource = new M_Roleresource 105 | { 106 | ResourceId = item.Id, 107 | RoleId = roleId 108 | }; 109 | resources.Add(roleresource); 110 | } 111 | affrows = dbContext.M_Roleresource.Delete.Where(f => f.RoleId == roleId).SaveChange(); 112 | affrows += dbContext.M_Roleresource.Insert.AddRange(resources).SaveChange(); 113 | } 114 | else 115 | { 116 | affrows = dbContext.M_Roleresource.Delete.Where(f => f.RoleId == roleId).SaveChange(); 117 | } 118 | 119 | return affrows > 0; 120 | } 121 | 122 | public bool ValidatorRole(int resourceId, int[] roleId) 123 | { 124 | return dbContext.M_Roleresource.Select.Where(f => f.ResourceId == resourceId && f.RoleId.In(roleId)).ToOne() != null; 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /examples/IdentityHost/Services/UserService.cs: -------------------------------------------------------------------------------- 1 | using IdentityHost.Helpers; 2 | using IdentityHost.Model; 3 | using MyStaging.Function; 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | namespace IdentityHost.Services 8 | { 9 | public class UserService : IManagerService 10 | { 11 | private readonly IdentityHostDbContext dbContext; 12 | public UserService(IdentityHostDbContext dbContext) 13 | { 14 | this.dbContext = dbContext; 15 | } 16 | 17 | public string ServiceName => nameof(UserService); 18 | 19 | public M_User Add(M_User user, List roles) 20 | { 21 | user.LoginName = user.LoginName.ToLower(); 22 | user.State = 0; 23 | user.CreateTime = DateTime.Now; 24 | user.Password = SecurityHelper.GetSHA256SignString(user.Password); 25 | 26 | user = dbContext.M_User.Insert.Add(user); 27 | UpdateRole(user.Id, roles); 28 | 29 | return user; 30 | } 31 | 32 | private void UpdateRole(int userId, List roles) 33 | { 34 | if (roles.Count > 0) 35 | { 36 | List maps = new List(); 37 | foreach (var item in roles) 38 | { 39 | var map = new M_Mapping 40 | { 41 | UserId = userId, 42 | CreateTime = DateTime.Now, 43 | RoleId = item 44 | }; 45 | maps.Add(map); 46 | } 47 | 48 | dbContext.M_Mapping.Insert.AddRange(maps).SaveChange(); 49 | } 50 | } 51 | 52 | public M_User Edit(int id, string name, string imgFace, string phone, List roles) 53 | { 54 | var user = dbContext.M_User.Update.SetValue(f => f.Name, name) 55 | .SetValue(f => f.ImgFace, imgFace) 56 | .SetValue(f => f.Phone, phone) 57 | .Where(f => f.Id == id) 58 | .SaveChange(); 59 | UpdateRole(id, roles); 60 | 61 | return user; 62 | } 63 | 64 | public M_User Detail(string loginName) 65 | { 66 | var user = dbContext.M_User.Select.Where(f => f.LoginName == loginName.ToLower()).ToOne(); 67 | 68 | return user; 69 | } 70 | 71 | public M_User Detail(int id) 72 | { 73 | var user = dbContext.M_User.Select.Where(f => f.Id == id).ToOne(); 74 | 75 | return user; 76 | } 77 | 78 | public bool UpdatePassword(int id, string password) 79 | { 80 | var newPassword = SecurityHelper.GetSHA256SignString(password); 81 | var user = dbContext.M_User.Update.SetValue(f => f.Password, newPassword).Where(f => f.Id == id).SaveChange(); 82 | 83 | return user != null; 84 | } 85 | 86 | public bool Delete(int id) 87 | { 88 | var user = dbContext.M_User.Update.SetValue(f => f.State, 3).Where(f => f.Id == id).SaveChange(); 89 | dbContext.M_Mapping.Delete.Where(f => f.UserId == user.Id).SaveChange(); 90 | 91 | return user != null; 92 | } 93 | 94 | public List List(string name, int state, int pageIndex, int pageSize) 95 | { 96 | var builder = dbContext.M_User.Select; 97 | if (state >= 0) 98 | { 99 | builder.Where(f => f.State == state); 100 | } 101 | if (!string.IsNullOrEmpty(name)) 102 | { 103 | builder.Where(f => f.Name.Like(name)); 104 | } 105 | var list = builder.Page(pageIndex, pageSize).OrderByDescing(f => f.CreateTime).ToList(); 106 | 107 | return list; 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /examples/IdentityHost/Startup.cs: -------------------------------------------------------------------------------- 1 | using IdentityHost.Converters; 2 | using IdentityHost.Extensions; 3 | using Microsoft.AspNetCore.Builder; 4 | using Microsoft.AspNetCore.Hosting; 5 | using Microsoft.Extensions.Configuration; 6 | using Microsoft.Extensions.DependencyInjection; 7 | using Microsoft.Extensions.Hosting; 8 | using System.Text.Encodings.Web; 9 | using System.Text.Json.Serialization; 10 | using System.Text.Unicode; 11 | 12 | namespace IdentityHost 13 | { 14 | public class Startup 15 | { 16 | public Startup(IConfiguration configuration, IWebHostEnvironment env) 17 | { 18 | Configuration = configuration; 19 | Env = env; 20 | } 21 | 22 | public IConfiguration Configuration { get; } 23 | public IWebHostEnvironment Env { get; } 24 | 25 | // This method gets called by the runtime. Use this method to add services to the container. 26 | public void ConfigureServices(IServiceCollection services) 27 | { 28 | services.AddMyStagingDbContenxt(Configuration) 29 | .AddIManagerService() 30 | .AddSingletonSerializerOptions() 31 | .AddCustomCors() 32 | .AddCustomSwagger(Env) 33 | .AddStackExchangeRedis(Configuration); 34 | 35 | services.AddControllers(p => 36 | { 37 | p.Filters.Add(); 38 | p.Filters.Add(); 39 | }); 40 | } 41 | 42 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 43 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 44 | { 45 | if (env.IsDevelopment()) 46 | { 47 | app.UseDeveloperExceptionPage(); 48 | } 49 | 50 | app.UseRouting() 51 | .UseAuthorization() 52 | .UseCustomizedSwagger() 53 | .UseCors() 54 | .UseMiddleware() 55 | .UseEndpoints(endpoints => 56 | { 57 | endpoints.MapControllers(); 58 | }); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /examples/IdentityHost/ViewModel/IdViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace IdentityHost.ViewModel 4 | { 5 | public class IdViewModel 6 | { 7 | /// 8 | /// Id 9 | /// 10 | [Required] public int Id { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /examples/IdentityHost/ViewModel/LoginViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace IdentityHost.ViewModel 4 | { 5 | public class LoginViewModel 6 | { 7 | /// 8 | /// 登录名 9 | /// 10 | [Required, MinLength(1, ErrorMessage = "账号长度1-10位"), MaxLength(6, ErrorMessage = "账号长度1-10位")] 11 | public string LoginName { get; set; } 12 | /// 13 | /// 密码 14 | /// 15 | [Required, MinLength(6, ErrorMessage = "密码长度6-16位"), MaxLength(16, ErrorMessage = "密码长度6-16位")] 16 | public string Password { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/IdentityHost/ViewModel/M_Resource.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace IdentityHost.Model 4 | { 5 | public partial class M_Resource 6 | { 7 | public List Children { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/IdentityHost/ViewModel/PageViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace IdentityHost.ViewModel 4 | { 5 | public class PageViewModel 6 | { 7 | /// 8 | /// 页码,默认=1 9 | /// 10 | public int PageIndex { get; set; } = 1; 11 | /// 12 | /// 每页查询数量,默认=10 13 | /// 14 | public int PageSize { get; set; } = 10; 15 | } 16 | 17 | public class UserListViewModel : PageViewModel 18 | { 19 | /// 20 | /// 状态,-1=全部,0=正常,1=未激活,2=冻结,3=删除 21 | /// 22 | [Required] public int State { get; set; } = 0; 23 | /// 24 | /// 名称,搜索条件,非模糊搜索 25 | /// 26 | public string Name { get; set; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /examples/IdentityHost/ViewModel/PasswordViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace IdentityHost.ViewModel 4 | { 5 | public class PasswordViewModel 6 | { 7 | /// 8 | /// 旧密码 9 | /// 10 | [Required, MinLength(6, ErrorMessage = "密码长度6-16位"), MaxLength(16, ErrorMessage = "密码长度6-16位")] 11 | public string OldPassword { get; set; } 12 | /// 13 | /// 新密码 14 | /// 15 | [Required, MinLength(6, ErrorMessage = "密码长度6-16位"), MaxLength(16, ErrorMessage = "密码长度6-16位")] 16 | public string NewPassword { get; set; } 17 | /// 18 | /// 重复新密码 19 | /// 20 | [Required, MinLength(6, ErrorMessage = "密码长度6-16位"), MaxLength(16, ErrorMessage = "密码长度6-16位"), Compare("NewPassword", ErrorMessage = "两次密码输入不一致")] 21 | public string RePassword { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/IdentityHost/ViewModel/R2EViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace IdentityHost.ViewModel 5 | { 6 | public class R2UViewModel 7 | { 8 | /// 9 | /// 角色Id 10 | /// 11 | public List RoleId { get; set; } = new List(); 12 | /// 13 | /// 员工Id 14 | /// 15 | [Required] public int UserId { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/IdentityHost/ViewModel/R2RViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace IdentityHost.ViewModel 5 | { 6 | public class R2RViewModel 7 | { 8 | /// 9 | /// 角色Id 10 | /// 11 | [Required] public int RoleId { get; set; } 12 | /// 13 | /// 资源Id 14 | /// 15 | public List ResourceId { get; set; } = new List(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/IdentityHost/ViewModel/ResourceViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace IdentityHost.ViewModel 4 | { 5 | public class AddResourceViewModel 6 | { 7 | /// 8 | /// 名称 9 | /// 10 | [Required] public string Name { get; set; } 11 | /// 12 | /// 资源内容 13 | /// 14 | [Required] public string Content { get; set; } 15 | /// 16 | /// 资源类型,0=API,1=网页元素 17 | /// 18 | [Required] public int Type { get; set; } 19 | /// 20 | /// 是否需要授权才允许访问 21 | /// 22 | [Required] public bool Authorize { get; set; } 23 | /// 24 | /// 资源分类编号 25 | /// 26 | public int? ParentId { get; set; } 27 | /// 28 | /// 排序号,倒序排序 29 | /// 30 | public int Sort { get; set; } 31 | } 32 | 33 | public class EditResourceViewModel : AddResourceViewModel 34 | { 35 | /// 36 | /// Id 37 | /// 38 | [Required] public int Id { get; set; } 39 | } 40 | 41 | public class ResourceListViewModel 42 | { 43 | /// 44 | /// 资源类型,0=API,1=网页元素,默认=0 45 | /// 46 | [Required] public int Type { get; set; } = 0; 47 | } 48 | 49 | public class ResourceRootViewModel 50 | { 51 | /// 52 | /// 资源类型,0=API,1=网页元素,默认= null 53 | /// 54 | public int? Type { get; set; } = null; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /examples/IdentityHost/ViewModel/RoleViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace IdentityHost.ViewModel 4 | { 5 | public class AddRoleViewModel 6 | { 7 | /// 8 | /// 角色名称 9 | /// 10 | [Required] public string Name { get; set; } 11 | } 12 | 13 | public class EditRoleViewModel : AddRoleViewModel 14 | { 15 | /// 16 | /// Id 17 | /// 18 | [Required] public int Id { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/IdentityHost/ViewModel/UserViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace IdentityHost.ViewModel 5 | { 6 | public class AddM_UserViewModel 7 | { 8 | /// 9 | /// 姓名 10 | /// 11 | [Required] 12 | public string Name { get; set; } 13 | /// 14 | /// 头像 15 | /// 16 | public string ImgFace { get; set; } 17 | /// 18 | /// 登录名 19 | /// 20 | [Required, MinLength(1, ErrorMessage = "1-10位"), MaxLength(10, ErrorMessage = "长度1-10位")] 21 | public string LoginName { get; set; } 22 | /// 23 | /// 手机号码 24 | /// 25 | public string Phone { get; set; } 26 | /// 27 | /// 密码 28 | /// 29 | [Required, MinLength(6, ErrorMessage = "密码长度6-16位"), MaxLength(16, ErrorMessage = "密码长度6-16位")] 30 | public string Password { get; set; } 31 | /// 32 | /// 角色列表 33 | /// 34 | public List Role { get; set; } = new List(); 35 | } 36 | 37 | public class EditUserViewModel 38 | { 39 | /// 40 | /// 用户编号 41 | /// 42 | public int Id { get; set; } 43 | 44 | /// 45 | /// 姓名 46 | /// 47 | [Required] 48 | public string Name { get; set; } 49 | /// 50 | /// 头像 51 | /// 52 | public string ImgFace { get; set; } 53 | /// 54 | /// 手机号码 55 | /// 56 | public string Phone { get; set; } 57 | /// 58 | /// 角色列表 59 | /// 60 | public List Role { get; set; } = new List(); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /examples/IdentityHost/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "ConnectionStrings": { 10 | "MySql": "server=127.0.0.1;user id=root;password=root;", 11 | "Redis": "127.0.0.1:6379,defaultDatabase=1,name=identity,abortConnect=false" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/IdentityHost/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "AllowedHosts": "*" 10 | } 11 | -------------------------------------------------------------------------------- /examples/Mysql/Model/Article.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.DataAnnotations; 2 | using System; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | 5 | namespace Mysql.Model 6 | { 7 | [Table(name: "Article", Schema = "mystaging")] 8 | public partial class Article 9 | { 10 | [PrimaryKey(AutoIncrement = true)] 11 | public int Id { get; set; } 12 | [Column(TypeName = "tinyint(1)")] 13 | public bool State { get; set; } 14 | public int UserId { get; set; } 15 | public string Title { get; set; } 16 | public string Content { get; set; } 17 | public DateTime CreateTime { get; set; } 18 | public string IP { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/Mysql/Model/Customer.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.DataAnnotations; 2 | using System.ComponentModel.DataAnnotations.Schema; 3 | 4 | namespace Mysql.Model 5 | { 6 | [Table(name: "Customer", Schema = "mystaging")] 7 | public partial class Customer 8 | { 9 | [PrimaryKey(AutoIncrement = true)] 10 | public int Id { get; set; } 11 | public string Name { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/Mysql/Model/M_Accesslog.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.DataAnnotations; 2 | using System; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | 5 | namespace Mysql.Model 6 | { 7 | [Table(name: "M_Accesslog", Schema = "mystaging")] 8 | public partial class M_Accesslog 9 | { 10 | [PrimaryKey(AutoIncrement = true)] 11 | public int Id { get; set; } 12 | /// 13 | /// 用户编号 14 | /// 15 | public int? UserId { get; set; } 16 | /// 17 | /// 资源内容 18 | /// 19 | public string Resource { get; set; } 20 | /// 21 | /// 资源编号 22 | /// 23 | public int? ResourceId { get; set; } 24 | /// 25 | /// 请求内容 26 | /// 27 | [Column(TypeName = "text")] 28 | public string ReqContent { get; set; } 29 | /// 30 | /// 响应内容 31 | /// 32 | [Column(TypeName = "text")] 33 | public string ResContent { get; set; } 34 | /// 35 | /// 客户端IP地址 36 | /// 37 | public string IP { get; set; } 38 | /// 39 | /// 响应代码 40 | /// 41 | public int? Code { get; set; } 42 | /// 43 | /// 备注 44 | /// 45 | public string Remark { get; set; } 46 | /// 47 | /// 创建时间 48 | /// 49 | public DateTime CreateTime { get; set; } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /examples/Mysql/Model/M_Mapping.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.DataAnnotations; 2 | using System; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | 5 | namespace Mysql.Model 6 | { 7 | [Table(name: "M_Mapping", Schema = "mystaging")] 8 | public partial class M_Mapping 9 | { 10 | /// 11 | /// 用户编号 12 | /// 13 | [PrimaryKey] 14 | public int UserId { get; set; } 15 | /// 16 | /// 角色编号 17 | /// 18 | public int RoleId { get; set; } 19 | /// 20 | /// 创建时间 21 | /// 22 | public DateTime CreateTime { get; set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/Mysql/Model/M_Resource.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.DataAnnotations; 2 | using System; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | 5 | namespace Mysql.Model 6 | { 7 | [Table(name: "M_Resource", Schema = "mystaging")] 8 | public partial class M_Resource 9 | { 10 | [PrimaryKey(AutoIncrement = true)] 11 | public int Id { get; set; } 12 | /// 13 | /// 上级编号 14 | /// 15 | public int? ParentId { get; set; } 16 | /// 17 | /// 资源名称 18 | /// 19 | public string Name { get; set; } 20 | /// 21 | /// 资源内容 22 | /// 23 | public string Content { get; set; } 24 | /// 25 | /// 资源类型,0=API,1=网页元素 26 | /// 27 | public int Type { get; set; } 28 | /// 29 | /// 状态,0=正常,1=冻结,2=删除 30 | /// 31 | public int State { get; set; } 32 | /// 33 | /// 是否需要授权访问 34 | /// 35 | [Column(TypeName = "tinyint(1)")] 36 | public bool Authorize { get; set; } 37 | /// 38 | /// 排序号,按数字顺序排序 39 | /// 40 | public int Sort { get; set; } 41 | /// 42 | /// 创建时间 43 | /// 44 | public DateTime CreateTime { get; set; } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /examples/Mysql/Model/M_Role.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.DataAnnotations; 2 | using System; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | 6 | namespace Mysql.Model 7 | { 8 | [Table(name: "M_Role", Schema = "mystaging")] 9 | public partial class M_Role 10 | { 11 | /// 12 | /// 编号 13 | /// 14 | [PrimaryKey(AutoIncrement = true)] 15 | public int Id { get; set; } 16 | /// 17 | /// 名称 18 | /// 19 | [Required] 20 | public string Name { get; set; } 21 | /// 22 | /// 状态,0=正常,1=冻结,2=删除 23 | /// 24 | public int State { get; set; } 25 | /// 26 | /// 创建时间 27 | /// 28 | public DateTime CreateTime { get; set; } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /examples/Mysql/Model/M_Roleresource.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.DataAnnotations; 2 | using System.ComponentModel.DataAnnotations.Schema; 3 | 4 | namespace Mysql.Model 5 | { 6 | [Table(name: "M_Roleresource", Schema = "mystaging")] 7 | public partial class M_Roleresource 8 | { 9 | /// 10 | /// 角色编号 11 | /// 12 | [PrimaryKey] 13 | public int RoleId { get; set; } 14 | /// 15 | /// 资源编号 16 | /// 17 | [PrimaryKey] 18 | public int ResourceId { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/Mysql/Model/M_User.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.DataAnnotations; 2 | using System; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | 6 | namespace Mysql.Model 7 | { 8 | [Table(name: "M_User", Schema = "mystaging")] 9 | public partial class M_User 10 | { 11 | /// 12 | /// 编号 13 | /// 14 | [PrimaryKey] 15 | public int Id { get; set; } 16 | /// 17 | /// 头像 18 | /// 19 | [Column(TypeName = "varchar(700)")] 20 | public string ImgFace { get; set; } 21 | /// 22 | /// 姓名 23 | /// 24 | [Required] 25 | public string Name { get; set; } 26 | /// 27 | /// 手机号码 28 | /// 29 | [Column(TypeName = "varchar(11)")] 30 | public string Phone { get; set; } 31 | /// 32 | /// 登录名 33 | /// 34 | [Required] 35 | public string LoginName { get; set; } 36 | /// 37 | /// 登录密码 38 | /// 39 | [Required] 40 | public string Password { get; set; } 41 | /// 42 | /// 状态,0=正常,1=未激活,2=冻结,3=删除 43 | /// 44 | public int State { get; set; } 45 | /// 46 | /// 创建时间 47 | /// 48 | public DateTime CreateTime { get; set; } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /examples/Mysql/Model/MysqlDbContext.cs: -------------------------------------------------------------------------------- 1 | using Mysql.Model; 2 | using MyStaging.Core; 3 | using MyStaging.Metadata; 4 | 5 | namespace Mysql 6 | { 7 | public partial class MysqlDbContext : DbContext 8 | { 9 | public MysqlDbContext(StagingOptions options) : base(options, ProviderType.MySql) 10 | { 11 | } 12 | 13 | public DbSet
Article { get; set; } 14 | public DbSet Customer { get; set; } 15 | public DbSet M_Accesslog { get; set; } 16 | public DbSet M_Mapping { get; set; } 17 | public DbSet M_Resource { get; set; } 18 | public DbSet M_Role { get; set; } 19 | public DbSet M_Roleresource { get; set; } 20 | public DbSet M_User { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /examples/Mysql/ModelExt/M_Resource.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Mysql.Model 4 | { 5 | public partial class M_Resource 6 | { 7 | public List Children { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/Mysql/Models.cs: -------------------------------------------------------------------------------- 1 | namespace Mysql 2 | { 3 | public class PageModel 4 | { 5 | public int UserId { get; set; } 6 | public string Keyword { get; set; } 7 | public int PageIndex { get; set; } = 1; 8 | public int PageSize { get; set; } = 10; 9 | } 10 | 11 | public struct IdModel 12 | { 13 | public int Id { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/Mysql/Mysql.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net6.0 5 | 6 | Exe 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /examples/Mysql/Mysql.csproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | true 5 | 6 | -------------------------------------------------------------------------------- /examples/Mysql/Program.cs: -------------------------------------------------------------------------------- 1 | using Mysql.Model; 2 | using Mysql.Services; 3 | using MyStaging.Metadata; 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | namespace Mysql 8 | { 9 | public class Program 10 | { 11 | private static MysqlDbContext dbContext; 12 | static void Main(string[] args) 13 | { 14 | var options = new StagingOptions("MySql", "server=127.0.0.1;user id=root;password=root;"); 15 | dbContext = new MysqlDbContext(options); 16 | 17 | AddUpdateDelete(); 18 | Query(); 19 | Transaction(); 20 | Console.WriteLine("success....."); 21 | Console.ReadKey(); 22 | } 23 | 24 | static void Transaction() 25 | { 26 | var customer = new Customer { Name = "好久不见" }; 27 | 28 | try 29 | { 30 | // 测试事务 31 | dbContext.BeginTransaction(); 32 | dbContext.Customer.Insert.Add(customer); 33 | List li = new List 34 | { 35 | new Customer { Name = "test" } 36 | }; 37 | dbContext.Customer.Insert.AddRange(li).SaveChange(); 38 | dbContext.Customer.Update.SetValue(a => a.Name, "12345").Where(f => f.Id == customer.Id).SaveChange(); 39 | dbContext.CommitTransaction(); 40 | 41 | ArticleService articleService = new ArticleService(dbContext); 42 | var art = articleService.Detail(13); 43 | if (art != null) 44 | { 45 | art = articleService.Update(art.Id, "修改了标题", art.Content); 46 | bool success = articleService.Delete(art.Id); 47 | } 48 | } 49 | catch (Exception e) 50 | { 51 | Console.WriteLine(e.Message); 52 | } 53 | } 54 | 55 | static void Query() 56 | { 57 | // 单个查询 58 | var article = dbContext.Customer.Select.Where(f => f.Id == 2 && f.Name == "Ron").ToOne(); 59 | // 列表查询,排序、分页、分组 60 | var articles = dbContext.Customer.Select.OrderBy(f => f.Name).Page(1, 10).GroupBy("Id,Name").ToList<(int id, string name)>("Id,Name"); 61 | // 表连接查询 62 | var ac = dbContext.Article.Select.InnerJoin("b", (a, b) => a.UserId == b.Id).Where(f => f.Id == 2).ToOne(); 63 | // 首字段查询,ToScalar 参数可以传递 Sql 参数,比如 SUM(x) 64 | var id = dbContext.Customer.Select.Where(f => f.Id == 2 && f.Name == "Ron").ToScalar("Id"); 65 | } 66 | 67 | static void AddUpdateDelete() 68 | { 69 | var art = new Article() 70 | { 71 | Content = "你是谁?你从哪里来?要到哪里去?", 72 | CreateTime = DateTime.Now, 73 | UserId = 43, 74 | IP = "127.0.0.1", 75 | State = true, 76 | Title = "振聋发聩的人生三问" 77 | }; 78 | 79 | var articles = new List
(); 80 | for (int i = 0; i < 10; i++) 81 | { 82 | articles.Add(art); 83 | } 84 | var a2 = dbContext.Article.Insert.Add(art); 85 | var affrows = dbContext.Article.Insert.AddRange(articles).SaveChange(); 86 | 87 | var a3 = dbContext.Article.Update.SetValue(f => f.Content, "未来已来,从这里开始").Where(f => f.Id == 1).SaveChange(); 88 | var a4 = dbContext.Article.Select.OrderByDescing(f => f.CreateTime).ToOne(); 89 | dbContext.Article.Delete.Where(f => f.Id == a4.Id).SaveChange(); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /examples/Mysql/Services/ArticleService.cs: -------------------------------------------------------------------------------- 1 | using Mysql.Model; 2 | using MyStaging.Function; 3 | using System.Collections.Generic; 4 | 5 | namespace Mysql.Services 6 | { 7 | public class ArticleService 8 | { 9 | private readonly MysqlDbContext dbContext; 10 | public ArticleService(MysqlDbContext dbContext) 11 | { 12 | this.dbContext = dbContext; 13 | } 14 | 15 | public List
List(PageModel model) 16 | { 17 | var build = dbContext.Article.Select.Page(model.PageIndex, model.PageSize).OrderByDescing(f => f.CreateTime); 18 | if (model.UserId > 0) 19 | { 20 | build.Where(f => f.UserId == model.UserId); 21 | } 22 | 23 | if (!string.IsNullOrEmpty(model.Keyword)) 24 | { 25 | build.Where(f => f.Title.Like(model.Keyword)); 26 | } 27 | 28 | return build.ToList(); 29 | } 30 | 31 | public Article Detail(int id) 32 | { 33 | if (id <= 0) 34 | { 35 | return null; 36 | } 37 | var detail = dbContext.Article.Select.Where(f => f.Id == id).ToOne(); 38 | 39 | return detail; 40 | } 41 | 42 | public Article Add(Article model) 43 | { 44 | 45 | var detail = dbContext.Article.Select.Where(f => f.Id == model.Id).ToOne(); 46 | 47 | return detail; 48 | } 49 | 50 | public Article Update(int id, string title, string content) 51 | { 52 | var article = dbContext.Article.Select.Where(f => f.Id == id).ToOne(); 53 | if (article == null) 54 | throw new KeyNotFoundException($"找不到Id={id} 的记录"); 55 | 56 | article = dbContext.Article.Update.SetValue(f => f.Content, content) 57 | .SetValue(f => f.Title, title) 58 | .Where(f => f.Id == article.Id) 59 | .SaveChange(); 60 | 61 | return article; 62 | } 63 | 64 | public bool Delete(int id) 65 | { 66 | var article = dbContext.Article.Select.Where(f => f.Id == id).ToOne(); 67 | if (article == null) 68 | throw new KeyNotFoundException($"找不到Id={id} 的记录"); 69 | 70 | var affrows = dbContext.Article.Delete.Where(f => f.Id == id).SaveChange(); 71 | 72 | return affrows > 0; 73 | } 74 | 75 | public long Total() 76 | { 77 | var total = dbContext.Article.Select.Where(f => f.State == true).Count(); 78 | 79 | return total; 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /examples/Mysql/Services/ResourceService.cs: -------------------------------------------------------------------------------- 1 | using Mysql.Model; 2 | using MyStaging.Function; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | 6 | namespace Mysql.Services 7 | { 8 | public class ResourceService 9 | { 10 | private readonly MysqlDbContext dbContext; 11 | public ResourceService(MysqlDbContext dbContext) 12 | { 13 | this.dbContext = dbContext; 14 | } 15 | 16 | public List List(int type) 17 | { 18 | var resources = dbContext.M_Resource.Select.Where(f => f.State == 0 && f.Type == type).ToList("DISTINCT a.*"); 19 | 20 | return GroupResource(resources); 21 | } 22 | 23 | public List ResourceByRole(int[] roles) 24 | { 25 | var resources = dbContext.M_Resource.Select.InnerJoin("b", (a, b) => a.Id == b.ResourceId) 26 | .Where(f => f.Type == 1) 27 | .Where(f => f.RoleId.In(roles)) 28 | .OrderByDescing(f => f.Sort) 29 | .ToList("DISTINCT a.*"); 30 | 31 | return GroupResource(resources); 32 | } 33 | 34 | private List GroupResource(List resources) 35 | { 36 | var result = new List(); 37 | var group = resources.OrderByDescending(f => f.Sort).GroupBy(g => g.ParentId); 38 | foreach (var g in group) 39 | { 40 | if (g.Key.HasValue) 41 | { 42 | result.AddRange(g.OrderByDescending(f => f.Sort).ToList()); 43 | } 44 | else 45 | { 46 | var item = resources.Where(f => f.Id == g.Key).FirstOrDefault(); 47 | if (item != null) 48 | { 49 | item.Children = g.OrderByDescending(f => f.Sort).ToList(); 50 | } 51 | } 52 | } 53 | 54 | return result; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /examples/Pgsql/Model/Article.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.DataAnnotations; 2 | using System; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | using System.Text.Json; 5 | 6 | namespace Pgsql.Model 7 | { 8 | [Table(name: "article", Schema = "public")] 9 | public partial class Article 10 | { 11 | [PrimaryKey] 12 | public string id { get; set; } 13 | [PrimaryKey] 14 | public string userid { get; set; } 15 | public string title { get; set; } 16 | public JsonElement content { get; set; } 17 | public DateTime createtime { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /examples/Pgsql/Model/PgsqlDbContext.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.Core; 2 | using MyStaging.Metadata; 3 | using Npgsql; 4 | using Pgsql.Model; 5 | using System; 6 | using System.Text.Json; 7 | 8 | namespace Pgsql 9 | { 10 | public class PgsqlDbContext : DbContext 11 | { 12 | public PgsqlDbContext(StagingOptions options) : base(options, ProviderType.PostgreSQL) 13 | { 14 | } 15 | 16 | static PgsqlDbContext() 17 | { 18 | Type[] jsonTypes = { typeof(JsonElement) }; 19 | NpgsqlNameTranslator translator = new(); 20 | //var dataSourceBuilder = new NpgsqlDataSourceBuilder("Host=localhost;Username=test;Password=test"); 21 | //dataSourceBuilder.MapEnum("public.et_data_state"); 22 | //dataSourceBuilder.UseNodaTime(); 23 | //await using var dataSource = dataSourceBuilder.Build(); 24 | NpgsqlConnection.GlobalTypeMapper.UseJsonNet(jsonTypes); 25 | NpgsqlConnection.GlobalTypeMapper.MapEnum("public.et_data_state", translator); 26 | NpgsqlConnection.GlobalTypeMapper.MapEnum("public.et_role", translator); 27 | } 28 | 29 | public DbSet User { get; set; } 30 | public DbSet Post { get; set; } 31 | public DbSet
Article { get; set; } 32 | public DbSet Topic { get; set; } 33 | public DbSet Udt3 { get; set; } 34 | } 35 | public partial class NpgsqlNameTranslator : INpgsqlNameTranslator 36 | { 37 | public string TranslateMemberName(string clrName) => clrName; 38 | public string TranslateTypeName(string clrTypeName) => clrTypeName; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /examples/Pgsql/Model/Post.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.DataAnnotations; 2 | using System; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | using System.Text.Json; 6 | 7 | namespace Pgsql.Model 8 | { 9 | [Table(name: "post", Schema = "public")] 10 | public partial class Post 11 | { 12 | [PrimaryKey] 13 | public Guid id { get; set; } 14 | [Required] 15 | public string title { get; set; } 16 | public JsonElement content { get; set; } 17 | [Column(TypeName = "public.et_data_state")] 18 | public et_data_state? state { get; set; } 19 | [Column(TypeName = "public.et_role")] 20 | public et_role? role { get; set; } 21 | [Column(TypeName = "json")] 22 | public JsonElement text { get; set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/Pgsql/Model/Topic.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.DataAnnotations; 2 | using System; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | 5 | namespace Pgsql.Model 6 | { 7 | [Table(name: "topic", Schema = "public")] 8 | public partial class Topic 9 | { 10 | [PrimaryKey] 11 | public Guid id { get; set; } 12 | public string title { get; set; } 13 | public DateTime? create_time { get; set; } 14 | public DateTime? update_time { get; set; } 15 | public DateTime? last_time { get; set; } 16 | public Guid? user_id { get; set; } 17 | public string name { get; set; } 18 | public int? age { get; set; } 19 | public bool? sex { get; set; } 20 | [Column(TypeName = "date")] 21 | public DateTime? createtime { get; set; } 22 | [Column(TypeName = "time")] 23 | public TimeSpan? updatetime { get; set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /examples/Pgsql/Model/Udt3.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.DataAnnotations; 2 | using System.ComponentModel.DataAnnotations.Schema; 3 | 4 | namespace Pgsql.Model 5 | { 6 | [Table(name: "udt3", Schema = "public")] 7 | public partial class Udt3 8 | { 9 | [PrimaryKey(AutoIncrement = true)] 10 | public int id { get; set; } 11 | public string name { get; set; } 12 | public short age { get; set; } 13 | [Column(TypeName = "numeric")] 14 | public decimal? a2 { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /examples/Pgsql/Model/User.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.DataAnnotations; 2 | using System; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | 6 | namespace Pgsql.Model 7 | { 8 | [Table(name: "user", Schema = "public")] 9 | public partial class User 10 | { 11 | [PrimaryKey] 12 | [Column(TypeName = "varchar(36)")] 13 | public string id { get; set; } 14 | [Required] 15 | [Column(TypeName = "varchar(200)")] 16 | public string loginname { get; set; } 17 | [Column(TypeName = "varchar(50)")] 18 | public string password { get; set; } 19 | public string nickname { get; set; } 20 | public bool? sex { get; set; } 21 | public int age { get; set; } 22 | [Column(TypeName = "numeric(10,2)")] 23 | public decimal money { get; set; } 24 | public DateTime createtime { get; set; } 25 | [Column(TypeName = "money")] 26 | public decimal wealth { get; set; } 27 | [Column(TypeName = "public.et_role")] 28 | public et_role? role { get; set; } 29 | public string IP { get; set; } 30 | public string[] citys { get; set; } 31 | public byte? sex2 { get; set; } 32 | public System.Collections.BitArray sex3 { get; set; } 33 | [Column(TypeName = "float4")] 34 | public double? sex4 { get; set; } 35 | [Column(TypeName = "float8")] 36 | public double? sex5 { get; set; } 37 | public TimeSpan? sex6 { get; set; } 38 | [Column(TypeName = "time")] 39 | public TimeSpan? sex7 { get; set; } 40 | [Column(TypeName = "date")] 41 | public DateTime? sex8 { get; set; } 42 | public DateTimeOffset? sex9 { get; set; } 43 | [Column(TypeName = "timestamptz")] 44 | public DateTime? sex10 { get; set; } 45 | [Column(TypeName = "text")] 46 | public string sex11 { get; set; } 47 | public short? sex12 { get; set; } 48 | public long? sex13 { get; set; } 49 | [Column(TypeName = "bpchar(1)")] 50 | public string sex14 { get; set; } 51 | [Column(TypeName = "float4")] 52 | public double? sex15 { get; set; } 53 | [Column(TypeName = "float4")] 54 | public double[] sex16 { get; set; } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /examples/Pgsql/Model/_Enums.cs: -------------------------------------------------------------------------------- 1 | namespace Pgsql.Model 2 | { 3 | public enum et_data_state 4 | { 5 | 正常, 6 | 删除, 7 | } 8 | public enum et_role 9 | { 10 | 管理员, 11 | 普通成员, 12 | 群主, 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /examples/Pgsql/Pgsql.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net6.0 5 | 6 | Exe 7 | 8 | false 9 | true 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /examples/Pgsql/Pgsql.csproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | true 5 | 6 | -------------------------------------------------------------------------------- /examples/Pgsql/Program.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.Metadata; 2 | using System; 3 | 4 | namespace Pgsql 5 | { 6 | 7 | class Program 8 | { 9 | [STAThread] 10 | static void Main(string[] args) 11 | { 12 | PgsqlDbContext dbContext = new PgsqlDbContext(new StagingOptions("Pgsql", "Host=127.0.0.1;Port=5432;Username=postgres;Password=postgres;Database=mystaging;")); 13 | new ContextTest().Start(); 14 | 15 | Console.ReadKey(); 16 | Console.WriteLine("success....."); 17 | } 18 | 19 | 20 | } 21 | } 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/MyStaging.Gen/MyStaging.Gen.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net6.0 6 | MyStaging.Gen 7 | 8 | 9 | 3.0.9 10 | LICENSE 11 | MyStaging.Gen 12 | MyStaging.Gen 13 | MyStaging.Gen 14 | true 15 | true 16 | mystaging.gen 17 | 18 | 19 | 20 | 21 | bin\Debug 22 | 1701;1702;1591 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | Never 32 | 33 | 34 | True 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /src/MyStaging.Gen/MyStaging.Gen.csproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | true 5 | 6 | -------------------------------------------------------------------------------- /src/MyStaging.Gen/Program.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.Common; 2 | using MyStaging.Interface; 3 | using MyStaging.Metadata; 4 | using System; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Reflection; 8 | using System.Runtime.Loader; 9 | 10 | namespace MyStaging.App 11 | { 12 | class Program 13 | { 14 | static void Main(string[] args) 15 | { 16 | if (args.Length == 0 || args[0] == "--help") 17 | { 18 | ShowHelp(); 19 | return; 20 | } 21 | 22 | try 23 | { 24 | var config = GetConfig(args); 25 | var factory = CreateGeneral(config.ProviderAssembly); 26 | if (config.Mode == GeneralInfo.Db) 27 | factory.DbFirst(config); 28 | else 29 | factory.CodeFirst(config); 30 | 31 | Console.WriteLine("OutputDir:{0}", config.OutputDir); 32 | Console.WriteLine("success."); 33 | } 34 | catch (Exception ex) 35 | { 36 | Console.WriteLine("{0}\n{1}", ex.Message, ex.StackTrace); 37 | } 38 | } 39 | 40 | static void ShowHelp() 41 | { 42 | Console.WriteLine(@"欢迎使用 MyStaging.Gen,查看帮助请使用命令 mystaging.gen --help 43 | 44 | //////////////////////////////////////////////////////// 45 | /// /// 46 | /// | | (_) /// 47 | /// _ __ ___ _ _ ___| |_ __ _ _ _ __ __ _ /// 48 | /// | '_ ` _ \| | | / __| __/ _` | | '_ \ / _` | /// 49 | /// | | | | | | |_| \__ \ || (_| | | | | | (_| | /// 50 | /// |_| |_| |_|\__, |___/\__\__,_|_|_| |_|\__, | /// 51 | /// __/ | __/ | /// 52 | /// |___/ |___/ /// 53 | /// /// 54 | //////////////////////////////////////////////////////// 55 | 56 | 要使用 MyStaging.Gen 请跟据下面的参数说明,执行创建实体对象映射. 57 | 58 | --help 查看帮助 59 | - m[mode,db[DbFirst] / code[CodeFirst],默认为 DbFirst 60 | - t[dbtype[Mysql / PostgreSQL],数据库提供程序] required 61 | - d[database,数据库连接字符串] required 62 | - n[name,数据库上下文名称] required 63 | - o[output,实体对象输出路径],默认为 { name}/ Model 64 | 65 | ==============示例============== 66 | CodeFirst: 67 | mystaging.gen -m code -t Mysql -n Mysql -o Model -d ""server=127.0.0.1;port=3306;user id=root;password=root;database=mystaging;"" 68 | DbFirst: 69 | mystaging.gen -m db -t Mysql -n Mysql -o Model -d ""server=127.0.0.1;port=3306;user id=root;password=root;database=mystaging;"" 70 | ================================ 71 | "); 72 | } 73 | 74 | static ProjectConfig GetConfig(string[] args) 75 | { 76 | var config = new ProjectConfig(); 77 | string mode = "db"; 78 | for (int i = 0; i < args.Length; i++) 79 | { 80 | var item = args[i].ToLower(); 81 | switch (item) 82 | { 83 | case "-d": 84 | config.ConnectionString = args[i + 1]; 85 | break; 86 | case "-n": config.ContextName = args[i + 1]; break; 87 | case "-o": config.OutputDir = args[i + 1]; break; 88 | case "-t": config.Provider = args[i + 1]; break; 89 | case "-m": mode = args[i + 1].ToLower(); break; 90 | } 91 | i++; 92 | } 93 | 94 | CheckNotNull.NotEmpty(config.ConnectionString, "-d 参数必须提供"); 95 | CheckNotNull.NotEmpty(config.ContextName, "-n 参数必须提供"); 96 | CheckNotNull.NotEmpty(config.Provider, "-t 参数必须提供"); 97 | CheckNotNull.NotEmpty(mode, "-m 参数必须提供"); 98 | 99 | if (mode != "db" && mode != "code") 100 | { 101 | throw new ArgumentException("-m 参数错误,必须为 db 或者 code"); 102 | } 103 | 104 | config.Mode = mode == "db" ? GeneralInfo.Db : GeneralInfo.Code; 105 | if (config.Mode == GeneralInfo.Db && string.IsNullOrEmpty(config.OutputDir)) 106 | { 107 | config.OutputDir = Path.Combine(config.ContextName, "Model"); 108 | } 109 | 110 | var fileName = "MyStaging." + config.Provider; 111 | config.ProviderAssembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(fileName)); 112 | 113 | return config; 114 | } 115 | 116 | static IGeneralFactory CreateGeneral(Assembly providerAssembly) 117 | { 118 | var type = providerAssembly.GetTypes().Where(f => f.GetInterface(typeof(IGeneralFactory).Name) != null).FirstOrDefault(); 119 | CheckNotNull.NotNull(typeof(IGeneralFactory), $"程序集中 {providerAssembly.FullName} 找不到 IGeneralFactory 的实现。"); 120 | return (IGeneralFactory)Activator.CreateInstance(type); 121 | } 122 | } 123 | } -------------------------------------------------------------------------------- /src/MyStaging.Gen/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "MyStaging.Gen": { 4 | "commandName": "Project" 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /src/MyStaging.Gen/build.bat: -------------------------------------------------------------------------------- 1 | mystaging.gen -m code -t MySql -n MySql -d "Host=127.0.0.1;Port=3306;Username=root;Password=root;Database=mystaging;" -------------------------------------------------------------------------------- /src/MyStaging.MySql/Core/DeleteBuilder`.cs: -------------------------------------------------------------------------------- 1 | using MySql.Data.MySqlClient; 2 | using MyStaging.Common; 3 | using MyStaging.Core; 4 | using MyStaging.Interface.Core; 5 | using MyStaging.Metadata; 6 | using System; 7 | using System.Data.Common; 8 | using System.Linq.Expressions; 9 | 10 | namespace MyStaging.MySql.Core 11 | { 12 | public class DeleteBuilder : ExpressionCondition, IDeleteBuilder where T : class 13 | { 14 | private readonly DbContext dbContext; 15 | public DeleteBuilder(DbContext dbContext) 16 | { 17 | this.dbContext = dbContext; 18 | } 19 | 20 | /// 21 | /// 该方法没有对sql注入进行参数化过滤 22 | /// 23 | /// 24 | /// 25 | public new IDeleteBuilder Where(string expression) 26 | { 27 | base.Where(expression); 28 | return this; 29 | } 30 | 31 | public new IDeleteBuilder Where(string formatCommad, params object[] pValue) 32 | { 33 | base.Where(formatCommad, pValue); 34 | return this; 35 | } 36 | 37 | public new IDeleteBuilder Where(Expression> predicate) => this.Where(null, predicate); 38 | 39 | public new IDeleteBuilder Where(Expression> predicate) => this.Where(null, predicate); 40 | 41 | public new IDeleteBuilder Where(string alisName, Expression> predicate) 42 | { 43 | base.Where(predicate); 44 | return this; 45 | } 46 | 47 | public override void AddParameter(string field, object value) 48 | { 49 | this.AddParameter(new MySqlParameter(field, value)); 50 | } 51 | 52 | public new IDeleteBuilder AddParameter(params DbParameter[] parameters) 53 | { 54 | base.AddParameter(parameters); 55 | return this; 56 | } 57 | 58 | /// 59 | /// 将当前更改保存到数据库 60 | /// 61 | /// 62 | public int SaveChange() 63 | { 64 | DeExpression(); 65 | CheckNotNull.NotEmpty(WhereConditions, "The delete operation must specify where conditions!"); 66 | this.ToSQL(); 67 | var affrows = dbContext.Execute.ExecuteNonQuery(System.Data.CommandType.Text, this.CommandText, Parameters.ToArray()); 68 | 69 | return affrows; 70 | } 71 | 72 | /// 73 | /// 重写方法 74 | /// 75 | /// 76 | public override string ToSQL() 77 | { 78 | string tableName = MyStagingUtils.GetMapping(typeof(T), ProviderType.MySql); 79 | this.CommandText = $"DELETE FROM {tableName} {"WHERE " + string.Join("\nAND ", WhereConditions)};"; 80 | 81 | return this.CommandText; 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/MyStaging.MySql/Core/UpdateBuilder`.cs: -------------------------------------------------------------------------------- 1 | using MySql.Data.MySqlClient; 2 | using MyStaging.Common; 3 | using MyStaging.Core; 4 | using MyStaging.Interface.Core; 5 | using MyStaging.Metadata; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Data; 9 | using System.Linq.Expressions; 10 | 11 | namespace MyStaging.MySql.Core 12 | { 13 | /// 14 | /// 数据库更新对象 15 | /// 16 | /// 17 | public class UpdateBuilder : ExpressionCondition, IUpdateBuilder where T : class 18 | { 19 | private readonly List setList = new List(); 20 | 21 | public UpdateBuilder() { } 22 | 23 | private readonly DbContext dbContext; 24 | public UpdateBuilder(DbContext dbContext) 25 | { 26 | this.dbContext = dbContext; 27 | } 28 | 29 | /// 30 | /// 该方法没有对sql注入进行参数化过滤 31 | /// 32 | /// 33 | /// 34 | public new IUpdateBuilder Where(string expression) 35 | { 36 | base.Where(expression); 37 | return this; 38 | } 39 | 40 | public new IUpdateBuilder Where(string formatCommad, params object[] pValue) 41 | { 42 | base.Where(formatCommad, pValue); 43 | return this; 44 | } 45 | 46 | public new IUpdateBuilder Where(Expression> predicate) => this.Where(null, predicate); 47 | 48 | public new IUpdateBuilder Where(Expression> predicate) => this.Where(null, predicate); 49 | 50 | public new IUpdateBuilder Where(string alisName, Expression> predicate) 51 | { 52 | base.Where(alisName, predicate); 53 | return this; 54 | } 55 | 56 | public override void AddParameter(string field, object value) 57 | { 58 | MySqlParameter p = new MySqlParameter(field, value); 59 | this.AddParameter(p); 60 | } 61 | 62 | /// 63 | /// 直接对当前字段执行增减操作 64 | /// 65 | /// 66 | /// 67 | /// 68 | public IUpdateBuilder SetIncrement(string field, decimal value) 69 | { 70 | setList.Add($"`{field}`=COALESCE({field},0) + {value}"); 71 | return this; 72 | } 73 | 74 | public IUpdateBuilder SetValue(Expression> selector, object value) 75 | { 76 | return SetValue(MyStagingUtils.GetMemberName(selector), value); 77 | } 78 | 79 | public IUpdateBuilder SetValue(string field, object value) 80 | { 81 | this.AddParameter(field, value); 82 | setList.Add($"`{field}` = @{field}"); 83 | return this; 84 | } 85 | 86 | /// 87 | /// 将当前更改保存到数据库 88 | /// 89 | /// 90 | public T SaveChange() 91 | { 92 | DeExpression(); 93 | 94 | CheckNotNull.NotEmpty(setList, "Fields to be updated must be provided!"); 95 | CheckNotNull.NotEmpty(WhereConditions, "The update operation must specify where conditions!"); 96 | 97 | try 98 | { 99 | this.ToSQL(); 100 | using var reader = dbContext.ByMaster().Execute.ExecuteDataReader(CommandType.Text, CommandText, this.Parameters.ToArray()); 101 | T obj = default; 102 | if (reader.Read()) 103 | { 104 | obj = GetResult(reader); 105 | } 106 | return obj; 107 | } 108 | finally 109 | { 110 | setList.Clear(); 111 | Clear(); 112 | } 113 | } 114 | 115 | /// 116 | /// 重写方法 117 | /// 118 | /// 119 | public override string ToSQL() 120 | { 121 | string tableName = MyStagingUtils.GetMapping(typeof(T), ProviderType.MySql); 122 | this.CommandText = $"UPDATE {tableName} a SET {string.Join(",", this.setList)} {"WHERE " + string.Join("\nAND ", WhereConditions)};"; 123 | this.CommandText += $"\n SELECT * FROM {tableName} {"WHERE " + string.Join("\nAND ", WhereConditions)};"; 124 | return this.CommandText; 125 | } 126 | 127 | public IUpdateBuilder SetArrayAppend(string field, object value) 128 | { 129 | throw new NotImplementedException(); 130 | } 131 | 132 | public IUpdateBuilder SetArrayRemove(string field, object value) 133 | { 134 | throw new NotImplementedException(); 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/MyStaging.MySql/Generals/EntityGeneral.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.Common; 2 | using MyStaging.Metadata; 3 | using System.IO; 4 | 5 | namespace MyStaging.MySql.Generals 6 | { 7 | public class EntityGeneral 8 | { 9 | #region identity 10 | private readonly TableInfo table; 11 | private readonly GeneralConfig config; 12 | #endregion 13 | 14 | public EntityGeneral(GeneralConfig config, TableInfo table) 15 | { 16 | this.config = config; 17 | this.table = table; 18 | } 19 | 20 | public void Create() 21 | { 22 | string _classname = MyStagingUtils.ToUpperPascal(this.table.Name); 23 | string _fileName = $"{config.ModelPath}/{_classname}.cs"; 24 | using StreamWriter writer = new StreamWriter(File.Create(_fileName), System.Text.Encoding.UTF8); 25 | writer.WriteLine("using System;"); 26 | writer.WriteLine("using System.Linq;"); 27 | writer.WriteLine("using System.Text.Json;"); 28 | writer.WriteLine("using MySql.Data.Types;"); 29 | writer.WriteLine("using System.ComponentModel.DataAnnotations.Schema;"); 30 | writer.WriteLine("using System.ComponentModel.DataAnnotations;"); 31 | writer.WriteLine("using MyStaging.DataAnnotations;"); 32 | writer.WriteLine(); 33 | writer.WriteLine($"namespace {config.ProjectName}.Model"); 34 | writer.WriteLine("{"); 35 | writer.WriteLine($"\t[Table(name: \"{this.table.Name}\", Schema = \"{table.Schema}\")]"); 36 | writer.WriteLine($"\tpublic partial class {_classname}"); 37 | writer.WriteLine("\t{"); 38 | 39 | foreach (var fi in table.Fields) 40 | { 41 | if (!string.IsNullOrEmpty(fi.Comment)) 42 | { 43 | writer.WriteLine("\t\t/// "); 44 | writer.WriteLine($"\t\t/// {fi.Comment}"); 45 | writer.WriteLine("\t\t/// "); 46 | } 47 | 48 | var autoincrement = fi.AutoIncrement ? "(AutoIncrement = true)" : ""; 49 | 50 | if (fi.PrimaryKey) 51 | writer.WriteLine($"\t\t[PrimaryKey{autoincrement}]"); 52 | if (fi.NotNull && fi.RelType == "string" && !fi.PrimaryKey) 53 | writer.WriteLine("\t\t[Required]"); 54 | if (!string.IsNullOrEmpty(fi.DbTypeFull)) 55 | writer.WriteLine($"\t\t[Column(TypeName = \"{fi.DbTypeFull}\")]"); 56 | 57 | writer.WriteLine($"\t\tpublic {fi.RelType} {fi.Name} {{ get; set; }}"); 58 | } 59 | 60 | writer.WriteLine("\t}"); 61 | writer.WriteLine("}"); 62 | writer.Flush(); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/MyStaging.MySql/MySqlStagingConnection.cs: -------------------------------------------------------------------------------- 1 | using MySql.Data.MySqlClient; 2 | using MyStaging.Core; 3 | using MyStaging.Interface; 4 | using System.Data.Common; 5 | 6 | namespace MyStaging.MySql 7 | { 8 | public partial class MySqlStagingConnection : IStagingConnection 9 | { 10 | public DbConnection GetConnection(string name, bool readOnly) 11 | { 12 | var model = ConnectionManager.Get(name, readOnly); 13 | var conn = new MySqlConnection(model.ConnectionString); 14 | 15 | return conn; 16 | } 17 | 18 | public void Refresh(string name, string master, params string[] slaves) 19 | { 20 | MySqlConnection.ClearAllPools(); 21 | ConnectionManager.Remove(name); 22 | ConnectionManager.Add(name, master, false); 23 | if (slaves?.Length > 0) 24 | { 25 | foreach (var conn in slaves) 26 | { 27 | ConnectionManager.Add(name, conn, true); 28 | } 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/MyStaging.MySql/MyStaging.MySql.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net6.0 5 | 3.0.9 6 | true 7 | false 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/MyStaging.MySql/MyStaging.MySql.csproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | true 5 | 6 | -------------------------------------------------------------------------------- /src/MyStaging.MySql/MysqlType.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.Metadata; 2 | using System.Collections.Generic; 3 | 4 | namespace MyStaging.MySql 5 | { 6 | public class MysqlType 7 | { 8 | private readonly static Dictionary csharpTypes = new Dictionary { 9 | { "char(36)", "Guid" }, 10 | { "tinyint(1)", "bool" }, 11 | { "tinyint", "sbyte" }, 12 | { "smallint", "short"}, 13 | { "integer", "int"}, 14 | { "mediumint", "int"}, 15 | { "int", "int"}, 16 | { "bigint", "long"}, 17 | { "bit", "ulong"}, 18 | { "real","double"}, 19 | { "double","double"}, 20 | { "float", "float"}, 21 | { "decimal", "decimal"}, 22 | { "numeric", "decimal"}, 23 | { "char", "string"}, 24 | { "varchar", "string"}, 25 | { "date", "DateTime"}, 26 | { "time", "TimeSpan"}, 27 | { "year", "DateTime"}, 28 | { "timestamp", "DateTime"}, 29 | { "datetime", "DateTime"}, 30 | { "tinyblob", "byte[]"}, 31 | { "blob", "byte[]" }, 32 | { "mediumblob", "byte[]" }, 33 | { "longblob", "byte[]" }, 34 | { "tinytext", "string" }, 35 | { "text", "string"}, 36 | { "mediumtext", "string"}, 37 | { "enum", "string"}, 38 | { "binary", "byte[]"}, 39 | { "varbinary", "byte[]"}, 40 | { "json", "JsonElement"} 41 | }; 42 | private readonly static Dictionary dbTypes = new Dictionary { 43 | { "Guid","char(36)" }, 44 | { "Int16", "smallint"}, 45 | { "Int32", "int"}, 46 | { "Int64", "bigint"}, 47 | { "UInt16", "smallint"}, 48 | { "UInt32", "int"}, 49 | { "UInt64", "bigint"}, 50 | { "Decimal", "decimal"}, 51 | { "Double","double"}, 52 | { "Single","float"}, 53 | { "Boolean", "tinyint(1)" }, 54 | { "Byte","bit" }, 55 | { "SByte","tinyint" }, 56 | { "Char","char" }, 57 | { "String","varchar" }, 58 | { "DateTimeOffset","datetime" }, 59 | { "TimeSpan","time"}, 60 | { "DateTime", "datetime"}, 61 | { "JsonElement", "json"} 62 | }; 63 | private readonly static Dictionary contrastTypes = new Dictionary { 64 | { "int", "int"}, 65 | { "smallint", "short"}, 66 | { "decimal", "decimal"}, 67 | { "double","double"}, 68 | { "float", "float"}, 69 | { "bigint", "long"}, 70 | { "char", "char"}, 71 | { "varchar", "string"}, 72 | { "binary", "byte[]" }, 73 | { "bit", "byte" }, 74 | { "timestamp", "DateTime" }, 75 | { "datetime", "DateTime" }, 76 | { "time", "TimeSpan"}, 77 | { "json", "JsonElement"}, 78 | { "tinyint", "sbyte" }, 79 | }; 80 | 81 | public static string SwitchToCSharp(string type) 82 | { 83 | if (csharpTypes.ContainsKey(type)) 84 | return csharpTypes[type]; 85 | else 86 | return type; 87 | } 88 | 89 | public static string ContrastType(string type) 90 | { 91 | foreach (var k in contrastTypes.Keys) 92 | { 93 | if (k == type) 94 | { 95 | return contrastTypes[k]; 96 | } 97 | } 98 | return null; 99 | } 100 | 101 | public static string GetDbType(string csType) 102 | { 103 | foreach (var k in dbTypes.Keys) 104 | { 105 | if (k == csType) 106 | { 107 | return dbTypes[k]; 108 | } 109 | } 110 | return null; 111 | } 112 | 113 | public static string GetRealType(DbFieldInfo fi) 114 | { 115 | var realType = fi.DbTypeFull ?? fi.DbType; 116 | return realType == "varchar" || realType == "char" ? realType + "(255)" : realType; 117 | } 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/MyStaging.PostgreSQL/Core/DeleteBuilder`.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.Common; 2 | using MyStaging.Core; 3 | using MyStaging.Interface.Core; 4 | using MyStaging.Metadata; 5 | using System; 6 | using System.Data.Common; 7 | using System.Linq.Expressions; 8 | 9 | namespace MyStaging.PostgreSQL.Core 10 | { 11 | public class DeleteBuilder : ExpressionCondition, IDeleteBuilder where T : class 12 | { 13 | private readonly DbContext dbContext; 14 | public DeleteBuilder(DbContext dbContext) 15 | { 16 | this.dbContext = dbContext; 17 | } 18 | 19 | /// 20 | /// 该方法没有对sql注入进行参数化过滤 21 | /// 22 | /// 23 | /// 24 | public new IDeleteBuilder Where(string expression) 25 | { 26 | base.Where(expression); 27 | return this; 28 | } 29 | 30 | public new IDeleteBuilder Where(string formatCommad, params object[] pValue) 31 | { 32 | base.Where(formatCommad, pValue); 33 | return this; 34 | } 35 | 36 | public new IDeleteBuilder Where(Expression> predicate) => this.Where(null, predicate); 37 | 38 | public new IDeleteBuilder Where(Expression> predicate) => this.Where(null, predicate); 39 | 40 | public new IDeleteBuilder Where(string alisName, Expression> predicate) 41 | { 42 | base.Where(predicate); 43 | return this; 44 | } 45 | 46 | public override void AddParameter(string field, object value) 47 | { 48 | this.AddParameter(new Npgsql.NpgsqlParameter(field, value)); 49 | } 50 | 51 | public new IDeleteBuilder AddParameter(params DbParameter[] parameters) 52 | { 53 | base.AddParameter(parameters); 54 | return this; 55 | } 56 | 57 | /// 58 | /// 将当前更改保存到数据库 59 | /// 60 | /// 61 | public int SaveChange() 62 | { 63 | DeExpression(); 64 | CheckNotNull.NotEmpty(WhereConditions, "The delete operation must specify where conditions!"); 65 | this.ToSQL(); 66 | var affrows = dbContext.Execute.ExecuteNonQuery(System.Data.CommandType.Text, this.CommandText, Parameters.ToArray()); 67 | 68 | return affrows; 69 | } 70 | 71 | /// 72 | /// 重写方法 73 | /// 74 | /// 75 | public override string ToSQL() 76 | { 77 | string tableName = MyStagingUtils.GetMapping(typeof(T), ProviderType.PostgreSQL); 78 | this.CommandText = $"DELETE FROM {tableName} {"WHERE " + string.Join("\nAND ", WhereConditions)}"; 79 | 80 | return this.CommandText; 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/MyStaging.PostgreSQL/Generals/EntityGeneral.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.Common; 2 | using MyStaging.Metadata; 3 | using System.IO; 4 | 5 | namespace MyStaging.PostgreSQL.Generals 6 | { 7 | public class EntityGeneral 8 | { 9 | #region identity 10 | private readonly TableInfo table; 11 | private readonly GeneralConfig config; 12 | #endregion 13 | 14 | public EntityGeneral(GeneralConfig config, TableInfo table) 15 | { 16 | this.config = config; 17 | this.table = table; 18 | } 19 | 20 | public void Create() 21 | { 22 | string _classname = CreateName(); 23 | string _fileName = $"{config.ModelPath}/{_classname}.cs"; 24 | using StreamWriter writer = new StreamWriter(File.Create(_fileName), System.Text.Encoding.UTF8); 25 | writer.WriteLine("using System;"); 26 | writer.WriteLine("using System.Linq;"); 27 | writer.WriteLine("using System.Text.Json;"); 28 | writer.WriteLine("using NpgsqlTypes;"); 29 | writer.WriteLine("using System.ComponentModel.DataAnnotations;"); 30 | writer.WriteLine("using System.ComponentModel.DataAnnotations.Schema;"); 31 | writer.WriteLine("using MyStaging.DataAnnotations;"); 32 | writer.WriteLine(); 33 | writer.WriteLine($"namespace {config.ProjectName}.Model"); 34 | writer.WriteLine("{"); 35 | writer.WriteLine($"\t[Table(name: \"{this.table.Name}\", Schema = \"{table.Schema}\")]"); 36 | writer.WriteLine($"\tpublic partial class {_classname}"); 37 | writer.WriteLine("\t{"); 38 | 39 | foreach (var fi in table.Fields) 40 | { 41 | if (!string.IsNullOrEmpty(fi.Comment)) 42 | { 43 | writer.WriteLine("\t\t/// "); 44 | writer.WriteLine($"\t\t/// {fi.Comment}"); 45 | writer.WriteLine("\t\t/// "); 46 | } 47 | 48 | var autoincrement = fi.AutoIncrement ? "(AutoIncrement = true)" : ""; 49 | 50 | if (fi.PrimaryKey) 51 | writer.WriteLine($"\t\t[PrimaryKey{autoincrement}]"); 52 | if (fi.NotNull && fi.RelType == "string" && !fi.PrimaryKey) 53 | writer.WriteLine("\t\t[Required]"); 54 | if (!string.IsNullOrEmpty(fi.DbTypeFull)) 55 | writer.WriteLine($"\t\t[Column(TypeName = \"{fi.DbTypeFull}\")]"); 56 | 57 | writer.WriteLine($"\t\tpublic {fi.RelType} {fi.Name} {{ get; set; }}"); 58 | } 59 | writer.WriteLine("\t}"); 60 | writer.WriteLine("}"); 61 | writer.Flush(); 62 | } 63 | 64 | private string CreateName(string separator = "") 65 | { 66 | var tableName = MyStagingUtils.ToUpperPascal(table.Name); 67 | string className; 68 | if (table.Schema == "public") 69 | { 70 | className = tableName; 71 | } 72 | else 73 | { 74 | className = $"{MyStagingUtils.ToUpperPascal(table.Schema)}{separator}{tableName}"; 75 | } 76 | 77 | return className; 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/MyStaging.PostgreSQL/MyStaging.PostgreSQL.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net6.0 5 | true 6 | 3.0.9 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/MyStaging.PostgreSQL/PgStagingConnection.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.Core; 2 | using MyStaging.Interface; 3 | using Npgsql; 4 | using System.Data.Common; 5 | 6 | namespace MyStaging.PostgreSQL 7 | { 8 | public partial class PgStagingConnection : IStagingConnection 9 | { 10 | public DbConnection GetConnection(string name, bool readOnly) 11 | { 12 | var model = ConnectionManager.Get(name, readOnly); 13 | var conn = new NpgsqlConnection(model.ConnectionString); 14 | 15 | return conn; 16 | } 17 | 18 | public void Refresh(string name, string master, params string[] slaves) 19 | { 20 | NpgsqlConnection.ClearAllPools(); 21 | ConnectionManager.Remove(name); 22 | ConnectionManager.Add(name, master, false); 23 | if (slaves?.Length > 0) 24 | { 25 | foreach (var conn in slaves) 26 | { 27 | ConnectionManager.Add(name, conn, true); 28 | } 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/MyStaging/Common/CheckNotNull.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace MyStaging.Common 5 | { 6 | public class CheckNotNull 7 | { 8 | public static void NotNull(T model, string parameterName) 9 | { 10 | if (model == null) 11 | throw new ArgumentNullException(parameterName); 12 | } 13 | 14 | public static void NotEmpty(IReadOnlyList value, string parameterName) 15 | { 16 | NotNull(value, parameterName); 17 | 18 | if (value.Count == 0) 19 | { 20 | throw new ArgumentException(parameterName); 21 | } 22 | } 23 | 24 | public static void NotEmpty(string value, string parameterName) 25 | { 26 | if (value is null) 27 | { 28 | throw new ArgumentNullException(parameterName); 29 | } 30 | else if (value.Trim().Length == 0) 31 | { 32 | throw new ArgumentException(parameterName); 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/MyStaging/Common/MyStagingUtils.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.Metadata; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | using System.Linq.Expressions; 6 | using System.Reflection; 7 | 8 | namespace MyStaging.Common 9 | { 10 | public class MyStagingUtils 11 | { 12 | public static Dictionary SQLSeparator = new Dictionary 13 | { 14 | {ProviderType.MySql,"`" }, 15 | {ProviderType.PostgreSQL,"\"" }, 16 | }; 17 | public static List GetDbFields(Type type) 18 | { 19 | var properties = new List(); 20 | var pis = type.GetProperties(); 21 | for (int j = 0; j < pis.Length; j++) 22 | { 23 | PropertyInfo pi = pis[j]; 24 | var attr = pi.GetCustomAttribute(typeof(NotMappedAttribute)); 25 | if (attr != null) continue; 26 | properties.Add(pi); 27 | } 28 | 29 | return properties; 30 | } 31 | 32 | /// 33 | /// 根据传入的实体对象获得数据库架构级表的映射名称 34 | /// 35 | /// 36 | public static string GetMapping(Type t, ProviderType providerType) 37 | { 38 | TypeInfo type = t.GetTypeInfo(); 39 | string tableName; 40 | if (type.GetCustomAttribute(typeof(TableAttribute)) is TableAttribute table) 41 | { 42 | tableName = GetTableName(table.Schema, table.Name, providerType); 43 | } 44 | else 45 | throw new NotSupportedException("在表连接实体上找不到特性 TableAttribute ,请确认数据库实体模型"); 46 | 47 | return tableName; 48 | } 49 | 50 | public static string GetTableName(TableInfo table, ProviderType providerType) => GetTableName(table.Schema, table.Name, providerType); 51 | 52 | private static string GetTableName(string schema, string name, ProviderType providerType) 53 | { 54 | var separator = SQLSeparator[providerType]; 55 | if (string.IsNullOrEmpty(schema)) 56 | return $"{separator}{name}{separator}"; 57 | else 58 | return $"{separator}{schema}{separator}.{separator}{name}{separator}"; 59 | } 60 | 61 | /// 62 | /// 复制两个对象的属性值 63 | /// 64 | /// 对象类型 65 | /// 待赋值的目标对象 66 | /// 复制的源对象 67 | /// 指定属性搜索范围 68 | public static void CopyProperty(T targetObj, T sourceObj, BindingFlags flags = BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Default | BindingFlags.Public) 69 | { 70 | PropertyInfo[] properties = sourceObj.GetType().GetProperties(flags); 71 | 72 | for (int i = 0; i < properties.Length; i++) 73 | { 74 | PropertyInfo pi = properties[i]; 75 | if (pi.CanWrite) 76 | pi.SetValue(targetObj, pi.GetValue(sourceObj, null), null); 77 | } 78 | } 79 | 80 | /// 81 | /// 获取表达式成员名称 82 | /// 83 | /// 84 | /// 85 | /// 86 | /// 87 | public static string GetMemberName(Expression> selector) 88 | { 89 | MemberExpression exp; 90 | if (selector.Body.NodeType == ExpressionType.Convert) 91 | { 92 | exp = (MemberExpression)((UnaryExpression)selector.Body).Operand; 93 | } 94 | else 95 | exp = (MemberExpression)selector.Body; 96 | 97 | return exp.Member.Name; 98 | } 99 | 100 | /// 101 | /// 将首字母转大写 102 | /// 103 | /// 104 | /// 105 | public static string ToUpperPascal(string text) 106 | { 107 | if (string.IsNullOrEmpty(text)) return text; 108 | 109 | string _first = text.Substring(0, 1).ToUpper(); 110 | string _value = text.Substring(1); 111 | 112 | return $"{_first}{_value}"; 113 | } 114 | 115 | /// 116 | /// 将首字母转小写 117 | /// 118 | /// 119 | /// 120 | public static string ToLowerPascal(string text) 121 | { 122 | if (string.IsNullOrEmpty(text)) return text; 123 | 124 | string _first = text.Substring(0, 1).ToLower(); 125 | string _value = text.Substring(1); 126 | 127 | return $"{_first}{_value}"; 128 | } 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/MyStaging/Common/ObjectId.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | 4 | namespace MyStaging.Common 5 | { 6 | public class ObjectId 7 | { 8 | private readonly static ObjectIdFactory factory = new ObjectIdFactory(); 9 | 10 | public ObjectId(byte[] hexData) 11 | { 12 | this.Hex = hexData; 13 | ReverseHex(); 14 | } 15 | 16 | public override string ToString() 17 | { 18 | if (Hex == null) 19 | Hex = new byte[12]; 20 | 21 | StringBuilder hexText = new StringBuilder(); 22 | for (int i = 0; i < this.Hex.Length; i++) 23 | { 24 | hexText.Append(this.Hex[i].ToString("x2")); 25 | } 26 | return hexText.ToString(); 27 | } 28 | 29 | public override int GetHashCode() => ToString().GetHashCode(); 30 | 31 | public ObjectId(string value) 32 | { 33 | if (string.IsNullOrEmpty(value)) throw new ArgumentNullException("value"); 34 | if (value.Length != 24) throw new ArgumentOutOfRangeException("value should be 24 characters"); 35 | 36 | Hex = new byte[12]; 37 | for (int i = 0; i < value.Length; i += 2) 38 | { 39 | try 40 | { 41 | Hex[i / 2] = Convert.ToByte(value.Substring(i, 2), 16); 42 | } 43 | catch 44 | { 45 | Hex[i / 2] = 0; 46 | } 47 | } 48 | 49 | ReverseHex(); 50 | } 51 | 52 | private void ReverseHex() 53 | { 54 | int copyIdx = 0; 55 | byte[] time = new byte[4]; 56 | Array.Copy(Hex, copyIdx, time, 0, 4); 57 | Array.Reverse(time); 58 | this.Timestamp = BitConverter.ToInt32(time, 0); 59 | copyIdx += 4; 60 | 61 | byte[] mid = new byte[4]; 62 | Array.Copy(Hex, copyIdx, mid, 0, 3); 63 | this.Machine = BitConverter.ToInt32(mid, 0); 64 | copyIdx += 3; 65 | 66 | byte[] pids = new byte[4]; 67 | Array.Copy(Hex, copyIdx, pids, 0, 2); 68 | Array.Reverse(pids); 69 | this.ProcessId = BitConverter.ToInt32(pids, 0); 70 | copyIdx += 2; 71 | 72 | byte[] inc = new byte[4]; 73 | Array.Copy(Hex, copyIdx, inc, 0, 3); 74 | Array.Reverse(inc); 75 | this.Increment = BitConverter.ToInt32(inc, 0); 76 | } 77 | 78 | public static ObjectId NewId() => factory.NewId(); 79 | 80 | public int CompareTo(ObjectId other) 81 | { 82 | if (other is null) 83 | return 1; 84 | 85 | for (int i = 0; i < Hex.Length; i++) 86 | { 87 | if (Hex[i] < other.Hex[i]) 88 | return -1; 89 | else if (Hex[i] > other.Hex[i]) 90 | return 1; 91 | } 92 | return 0; 93 | } 94 | 95 | public bool Equals(ObjectId other) => CompareTo(other) == 0; 96 | 97 | public static bool operator <(ObjectId a, ObjectId b) => a.CompareTo(b) < 0; 98 | 99 | public static bool operator <=(ObjectId a, ObjectId b) => a.CompareTo(b) <= 0; 100 | 101 | public static bool operator ==(ObjectId a, ObjectId b) => a.Equals(b); 102 | 103 | public override bool Equals(object obj) => base.Equals(obj); 104 | 105 | public static bool operator !=(ObjectId a, ObjectId b) => !(a == b); 106 | 107 | public static bool operator >=(ObjectId a, ObjectId b) => a.CompareTo(b) >= 0; 108 | 109 | public static bool operator >(ObjectId a, ObjectId b) => a.CompareTo(b) > 0; 110 | 111 | public static implicit operator string(ObjectId objectId) => objectId.ToString(); 112 | 113 | public static implicit operator ObjectId(string objectId) => new ObjectId(objectId); 114 | 115 | public static ObjectId Empty { get { return new ObjectId("000000000000000000000000"); } } 116 | 117 | public byte[] Hex { get; private set; } 118 | 119 | public int Timestamp { get; private set; } 120 | 121 | public int Machine { get; private set; } 122 | 123 | public int ProcessId { get; private set; } 124 | 125 | public int Increment { get; private set; } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/MyStaging/Common/ObjectIdFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Net; 4 | using System.Security.Cryptography; 5 | using System.Text; 6 | 7 | namespace MyStaging.Common 8 | { 9 | public class ObjectIdFactory 10 | { 11 | private int increment; 12 | private readonly byte[] pidHex; 13 | private readonly byte[] machineHash; 14 | private readonly UTF8Encoding utf8 = new UTF8Encoding(false); 15 | private readonly DateTime unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); 16 | 17 | public ObjectIdFactory() 18 | { 19 | MD5 md5 = MD5.Create(); 20 | machineHash = md5.ComputeHash(utf8.GetBytes(Dns.GetHostName())); 21 | pidHex = BitConverter.GetBytes(Process.GetCurrentProcess().Id); 22 | Array.Reverse(pidHex); 23 | } 24 | 25 | /// 26 | /// 产生一个新的 24 位唯一编号 27 | /// 28 | /// 29 | public ObjectId NewId() 30 | { 31 | int copyIdx = 0; 32 | byte[] hex = new byte[12]; 33 | 34 | byte[] time = BitConverter.GetBytes(GetTimestamp()); 35 | Array.Reverse(time); 36 | Array.Copy(time, 0, hex, copyIdx, 4); 37 | copyIdx += 4; 38 | 39 | Array.Copy(machineHash, 0, hex, copyIdx, 3); 40 | copyIdx += 3; 41 | 42 | Array.Copy(pidHex, 2, hex, copyIdx, 2); 43 | copyIdx += 2; 44 | 45 | byte[] inc = BitConverter.GetBytes(GetIncrement()); 46 | Array.Reverse(inc); 47 | Array.Copy(inc, 1, hex, copyIdx, 3); 48 | 49 | return new ObjectId(hex); 50 | } 51 | 52 | private int GetIncrement() => System.Threading.Interlocked.Increment(ref increment); 53 | 54 | private int GetTimestamp() => Convert.ToInt32(Math.Floor((DateTime.UtcNow - unixEpoch).TotalSeconds)); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/MyStaging/Core/ConnectionManager.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.Metadata; 2 | using System; 3 | using System.Collections.Concurrent; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | 7 | namespace MyStaging.Core 8 | { 9 | public class ConnectionManager 10 | { 11 | private readonly static ConcurrentDictionary> dict = new(); 12 | 13 | public static void Add(string name, string connectionString, bool readOnly) 14 | { 15 | var conn = new ConnectionModel 16 | { 17 | ConnectionString = connectionString, 18 | ReadOnly = readOnly 19 | }; 20 | 21 | if (dict.ContainsKey(name)) 22 | { 23 | dict[name].Add(conn); 24 | } 25 | else 26 | { 27 | var models = new List() 28 | { 29 | conn 30 | }; 31 | dict.TryAdd(name, models); 32 | } 33 | } 34 | 35 | public static ConnectionModel Get(string name, bool readOnly) 36 | { 37 | dict.TryGetValue(name, out List models); 38 | if (models == null || models.Count == 0) 39 | { 40 | throw new InvalidOperationException("已无可用的数据库连接"); 41 | } 42 | 43 | ConnectionModel connection = models.Count == 1 ? models[0] : models.Where(f => f.ReadOnly == readOnly).OrderBy(f => f.Used).First(); 44 | 45 | if (connection.Used < long.MaxValue) 46 | { 47 | connection.Used++; 48 | } 49 | 50 | return connection; 51 | } 52 | 53 | public static void Remove(string name) 54 | { 55 | dict.TryRemove(name, out _); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/MyStaging/Core/DbRecord.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data; 3 | using System.Data.Common; 4 | using System.Reflection; 5 | using System.Text.Json; 6 | 7 | namespace MyStaging.Core 8 | { 9 | public abstract class DbRecord 10 | { 11 | public TResult GetResult(DbDataReader dr) 12 | { 13 | Type resultType = typeof(TResult); 14 | bool isEnum = resultType.IsEnum; 15 | 16 | TResult result; 17 | if (resultType == typeof(JsonElement)) 18 | { 19 | result = (TResult)GetJsonElement(dr); 20 | } 21 | else if (IsValueType(resultType)) 22 | { 23 | int columnIndex = -1; 24 | result = (TResult)GetValueTuple(resultType, dr, ref columnIndex); 25 | } 26 | else if (isEnum) 27 | { 28 | result = (TResult)GetValueType(resultType, dr); 29 | } 30 | else 31 | { 32 | result = Activator.CreateInstance(); 33 | var properties = resultType.GetProperties(); 34 | foreach (var pi in properties) 35 | { 36 | var value = dr[pi.Name]; 37 | if (value == DBNull.Value) 38 | continue; 39 | else if (pi.PropertyType.Name == "JsonElement") 40 | pi.SetValue(result, JsonDocument.Parse(value.ToString()).RootElement); 41 | else 42 | pi.SetValue(result, value); 43 | } 44 | } 45 | 46 | 47 | return result; 48 | } 49 | 50 | /// 51 | /// 检查查询结果对象是否为元组类型 52 | /// 53 | /// 54 | /// 55 | public static bool IsValueType(Type type) 56 | { 57 | return (type.Namespace == "System" && type.Name.StartsWith("String")) || (type.BaseType == typeof(ValueType)); 58 | } 59 | 60 | /// 61 | /// 从数据库流中读取值并转换为指定的对象类型 62 | /// 63 | /// 对象类型 64 | /// 查询流 65 | /// 66 | public object GetValueType(Type objType, IDataReader dr) 67 | { 68 | object dbValue = dr[0]; 69 | dbValue = dbValue is DBNull ? null : dbValue; 70 | dbValue = Convert.ChangeType(dbValue, objType); 71 | 72 | return dbValue; 73 | } 74 | 75 | /// 76 | /// 将查询结果转换为元组对象 77 | /// 78 | /// 元组类型 79 | /// 查询流 80 | /// dr index 81 | /// 82 | public object GetValueTuple(Type objType, IDataReader dr, ref int columnIndex) 83 | { 84 | bool isTuple = objType.Namespace == "System" && objType.Name.StartsWith("ValueTuple`"); 85 | if (isTuple) 86 | { 87 | FieldInfo[] fs = objType.GetFields(); 88 | Type[] types = new Type[fs.Length]; 89 | object[] parameters = new object[fs.Length]; 90 | for (int i = 0; i < fs.Length; i++) 91 | { 92 | types[i] = fs[i].FieldType; 93 | parameters[i] = GetValueTuple(types[i], dr, ref columnIndex); 94 | } 95 | ConstructorInfo info = objType.GetConstructor(types); 96 | return info.Invoke(parameters); 97 | } 98 | ++columnIndex; 99 | object dbValue = dr[columnIndex]; 100 | dbValue = dbValue is DBNull ? null : dbValue; 101 | 102 | return dbValue; 103 | } 104 | 105 | /// 106 | /// 将查询结果转换为 JsonElement 对象 107 | /// 108 | /// 查询流 109 | /// 110 | public object GetJsonElement(IDataReader dr) 111 | { 112 | object dbValue = dr[0]; 113 | if (dbValue is DBNull) 114 | return null; 115 | else 116 | return JsonDocument.Parse(dbValue.ToString()).RootElement; 117 | } 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/MyStaging/Core/DbSet`.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.Interface.Core; 2 | 3 | namespace MyStaging.Core 4 | { 5 | public class DbSet where T : class 6 | { 7 | public ISelectBuilder Select { get; set; } 8 | public IInsertBuilder Insert { get; set; } 9 | public IUpdateBuilder Update { get; set; } 10 | public IDeleteBuilder Delete { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/MyStaging/DataAnnotations/PrimaryKeyAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MyStaging.DataAnnotations 4 | { 5 | public class PrimaryKeyAttribute : Attribute 6 | { 7 | public bool AutoIncrement { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/MyStaging/Function/SqlFunction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MyStaging.Function 4 | { 5 | public static class SqlFunction 6 | { 7 | /// 8 | /// 转换为数据库查询 in 查询 9 | /// 10 | /// in 查询的字段类型 11 | /// 12 | /// in 查询的值列表 13 | /// 14 | public static bool In(this T sender, params T[] vals) 15 | { 16 | if (vals is null) 17 | { 18 | throw new ArgumentNullException(nameof(vals)); 19 | } 20 | 21 | return true; 22 | } 23 | 24 | public static bool In(this T? sender, params T[] _vals) where T : struct 25 | { 26 | if (sender is null) 27 | { 28 | throw new ArgumentNullException(nameof(sender)); 29 | } 30 | 31 | if (_vals is null) 32 | { 33 | throw new ArgumentNullException(nameof(_vals)); 34 | } 35 | 36 | return true; 37 | } 38 | 39 | /// 40 | /// 转换为数据库查询 not in 查询 41 | /// 42 | /// not in 查询的字段类型 43 | /// 44 | /// not in 查询的值列表 45 | /// 46 | public static bool NotIn(this T sender, params T[] vals) 47 | { 48 | return true; 49 | } 50 | 51 | public static bool NotIn(this T? sender, params T[] vals) where T : struct 52 | { 53 | return true; 54 | } 55 | 56 | /// 57 | /// 转换为数据库查询 like 查询 58 | /// 59 | /// like 查询的字段类型 60 | /// 61 | public static bool Like(this T sender, T val) 62 | { 63 | return true; 64 | } 65 | 66 | /// 67 | /// 转换为数据库查询 not like 查询 68 | /// 69 | /// not like 查询的字段类型 70 | /// 71 | /// not like 查询的值列表 72 | /// 73 | public static bool NotLike(this T sender, T vals) 74 | { 75 | return true; 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/MyStaging/Interface/Core/IDeleteBuilder`.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data.Common; 3 | using System.Linq.Expressions; 4 | 5 | namespace MyStaging.Interface.Core 6 | { 7 | /// 8 | /// 数据库更新对象 9 | /// 10 | /// 11 | public interface IDeleteBuilder : ISaveChanged where T : class 12 | { 13 | IDeleteBuilder Where(string expression); 14 | 15 | IDeleteBuilder Where(string formatCommad, params object[] pValue); 16 | 17 | IDeleteBuilder Where(Expression> predicate); 18 | 19 | IDeleteBuilder Where(Expression> predicate); 20 | 21 | IDeleteBuilder Where(string alisName, Expression> predicate); 22 | 23 | void AddParameter(string field, object value); 24 | 25 | void AddParameter(params DbParameter[] parameters); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/MyStaging/Interface/Core/IInsertBuilder`.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace MyStaging.Interface.Core 4 | { 5 | /// 6 | /// 数据库更新对象 7 | /// 8 | /// 9 | public interface IInsertBuilder : ISaveChanged where T : class 10 | { 11 | T Add(T model); 12 | 13 | /// 14 | /// 调用该方法必须在最后调用 SaveChange(),否则不会将数据保存到数据库 15 | /// 16 | /// 17 | /// 18 | IInsertBuilder AddRange(List items); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/MyStaging/Interface/Core/IUpdateBuilder`.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data.Common; 3 | using System.Linq.Expressions; 4 | 5 | namespace MyStaging.Interface.Core 6 | { 7 | /// 8 | /// 数据库更新对象 9 | /// 10 | /// 11 | public interface IUpdateBuilder where T : class 12 | { 13 | IUpdateBuilder Where(string expression); 14 | 15 | IUpdateBuilder Where(string formatCommad, params object[] pValue); 16 | 17 | IUpdateBuilder Where(Expression> predicate); 18 | 19 | IUpdateBuilder Where(Expression> predicate); 20 | 21 | IUpdateBuilder Where(string alisName, Expression> predicate); 22 | 23 | void AddParameter(string field, object value); 24 | 25 | void AddParameter(params DbParameter[] parameters); 26 | 27 | IUpdateBuilder SetValue(Expression> selector, object value); 28 | 29 | IUpdateBuilder SetValue(string field, object value); 30 | 31 | IUpdateBuilder SetIncrement(string field, decimal value); 32 | 33 | IUpdateBuilder SetArrayAppend(string field, object value); 34 | 35 | IUpdateBuilder SetArrayRemove(string field, object value); 36 | 37 | T SaveChange(); 38 | 39 | string ToSQL(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/MyStaging/Interface/IGeneralFactory.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.Metadata; 2 | 3 | namespace MyStaging.Interface 4 | { 5 | public interface IGeneralFactory 6 | { 7 | void DbFirst(ProjectConfig config); 8 | void CodeFirst(ProjectConfig config); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/MyStaging/Interface/IQueryPipeLine.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data.Common; 4 | 5 | namespace MyStaging.Interface 6 | { 7 | public interface IQueryPipeLine 8 | { 9 | Type ResultType { get; set; } 10 | string CommandText { get; set; } 11 | List Parameters { get; set; } 12 | } 13 | 14 | public class QueryPipeLine 15 | { 16 | public Type ResultType { get; set; } 17 | public string CommandText { get; set; } 18 | public List Parameters { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/MyStaging/Interface/ISaveChanged.cs: -------------------------------------------------------------------------------- 1 | namespace MyStaging.Interface 2 | { 3 | public interface ISaveChanged 4 | { 5 | /// 6 | /// 将当前更改保存到数据库 7 | /// 8 | /// 9 | int SaveChange(); 10 | 11 | string ToSQL(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/MyStaging/Interface/IStagingConnection.cs: -------------------------------------------------------------------------------- 1 | using System.Data.Common; 2 | 3 | namespace MyStaging.Interface 4 | { 5 | public interface IStagingConnection 6 | { 7 | /// 8 | /// 9 | /// 10 | /// 11 | /// 12 | /// 13 | DbConnection GetConnection(string name, bool readOnly); 14 | 15 | /// 16 | /// 刷新数据库连接 17 | /// 18 | /// 19 | /// 20 | /// 21 | void Refresh(string name, string master, params string[] slaves); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/MyStaging/Metadata/ConnectionModel.cs: -------------------------------------------------------------------------------- 1 | namespace MyStaging.Metadata 2 | { 3 | public class ConnectionModel 4 | { 5 | public bool ReadOnly { get; set; } 6 | 7 | public string ConnectionString { get; set; } 8 | 9 | public long Used { get; internal set; } 10 | 11 | public long Error { get; internal set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/MyStaging/Metadata/ConstraintInfo.cs: -------------------------------------------------------------------------------- 1 | namespace MyStaging.Metadata 2 | { 3 | public class ConstraintInfo 4 | { 5 | public string Field { get; set; } 6 | public string Name { get; set; } 7 | public ConstraintType Type { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/MyStaging/Metadata/ConstraintType.cs: -------------------------------------------------------------------------------- 1 | namespace MyStaging.Metadata 2 | { 3 | public enum ConstraintType 4 | { 5 | PK, 6 | FK, 7 | UNQ 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/MyStaging/Metadata/DbFieldInfo.cs: -------------------------------------------------------------------------------- 1 | namespace MyStaging.Metadata 2 | { 3 | public class DbFieldInfo 4 | { 5 | public int Oid { get; set; } 6 | public string Name { get; set; } 7 | public long Length { get; set; } 8 | public int Numeric_scale { get; set; } 9 | public string Comment { get; set; } 10 | public string CsType { get; set; } 11 | public string RelType { get; set; } 12 | public string DbType { get; set; } 13 | public string DbTypeFull { get; set; } 14 | public bool PrimaryKey { get; set; } 15 | public bool IsArray { get; set; } 16 | public bool NotNull { get; set; } 17 | public bool AutoIncrement { get; set; } 18 | public string ColumnDefault { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/MyStaging/Metadata/EnumTypeInfo.cs: -------------------------------------------------------------------------------- 1 | namespace MyStaging.Metadata 2 | { 3 | public class EnumTypeInfo 4 | { 5 | public int Oid { get; set; } 6 | public string TypeName { get; set; } 7 | public string NspName { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/MyStaging/Metadata/ExpressionInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | 4 | namespace MyStaging.Metadata 5 | { 6 | /// 7 | /// lambda 表达式模型对象 8 | /// 9 | public class ExpressionInfo 10 | { 11 | /// 12 | /// 连接表别名 13 | /// 14 | public string UnionAlisName { get; set; } 15 | /// 16 | /// 实体对象模型类型 17 | /// 18 | public Type Model { get; set; } 19 | /// 20 | /// 查询表达式 21 | /// 22 | public Expression Body { get; set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/MyStaging/Metadata/ExpressionUnionInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | 4 | namespace MyStaging.Metadata 5 | { 6 | /// 7 | /// 连接查询表达式模型 8 | /// 9 | public class ExpressionUnionInfo 10 | { 11 | /// 12 | /// 连接别名 13 | /// 14 | public string AlisName { get; set; } 15 | /// 16 | /// 连接别名 17 | /// 18 | public string UnionAlisName { get; set; } 19 | /// 20 | /// 连接的实体对象模型类型 21 | /// 22 | public Type Model { get; set; } 23 | /// 24 | /// 主查询实体对象模型 25 | /// 26 | public Type MasterType { get; set; } 27 | /// 28 | /// on 连接查询表达式 29 | /// 30 | public Expression Body { get; set; } 31 | /// 32 | /// 连接查询的类型 33 | /// 34 | public UnionType UnionType { get; set; } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/MyStaging/Metadata/GeneralConfig.cs: -------------------------------------------------------------------------------- 1 | namespace MyStaging.Metadata 2 | { 3 | public class GeneralConfig 4 | { 5 | public string OutputDir { get; set; } 6 | public string ProjectName { get; set; } 7 | public string ModelPath { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/MyStaging/Metadata/GeneralInfo.cs: -------------------------------------------------------------------------------- 1 | namespace MyStaging.Metadata 2 | { 3 | public enum GeneralInfo 4 | { 5 | Db, 6 | Code 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/MyStaging/Metadata/ProjectConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | 3 | namespace MyStaging.Metadata 4 | { 5 | public class ProjectConfig 6 | { 7 | public string OutputDir { get; set; } 8 | public string ContextName { get; set; } 9 | public string ConnectionString { get; set; } 10 | public string Provider { get; set; } 11 | public GeneralInfo Mode { get; set; } 12 | public Assembly ProviderAssembly { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/MyStaging/Metadata/ProviderType.cs: -------------------------------------------------------------------------------- 1 | namespace MyStaging.Metadata 2 | { 3 | public enum ProviderType 4 | { 5 | MySql, 6 | PostgreSQL 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/MyStaging/Metadata/StagingOptions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Logging; 2 | using MyStaging.Interface; 3 | using System; 4 | 5 | namespace MyStaging.Metadata 6 | { 7 | public class StagingOptions 8 | { 9 | public StagingOptions(string name, string master, params string[] slaves) 10 | { 11 | if (string.IsNullOrEmpty(name)) 12 | throw new ArgumentNullException(nameof(name)); 13 | 14 | if (string.IsNullOrEmpty(master)) 15 | throw new ArgumentNullException(nameof(master)); 16 | 17 | this.Master = master; 18 | this.Slaves = slaves; 19 | this.Name = name; 20 | } 21 | 22 | public string Name { get; } 23 | public ILogger Logger { get; set; } 24 | public IStagingConnection Connection { get; set; } 25 | public ProviderType Provider { get; set; } 26 | public string Master { get; set; } 27 | public string[] Slaves { get; set; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/MyStaging/Metadata/TableInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace MyStaging.Metadata 5 | { 6 | public class TableInfo 7 | { 8 | public string Schema { get; set; } 9 | public string Name { get; set; } 10 | public TableType Type { get; set; } 11 | public Type EntityType { get; set; } 12 | public List Fields { get; set; } = new List(); 13 | public List Constraints { get; set; } = new List(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/MyStaging/Metadata/TableType.cs: -------------------------------------------------------------------------------- 1 | namespace MyStaging.Metadata 2 | { 3 | public enum TableType 4 | { 5 | Table, 6 | View 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/MyStaging/Metadata/UnionType.cs: -------------------------------------------------------------------------------- 1 | namespace MyStaging.Metadata 2 | { 3 | /// 4 | /// Union query type 5 | /// 6 | public enum UnionType 7 | { 8 | /// 9 | /// Inner join 10 | /// 11 | INNER_JOIN, 12 | /// 13 | /// Left join 14 | /// 15 | LEFT_JOIN, 16 | /// 17 | /// Right join 18 | /// 19 | RIGHT_JOIN, 20 | /// 21 | /// Left outer join 22 | /// 23 | LEFT_OUTER_JOIN, 24 | /// 25 | /// Right outer join 26 | /// 27 | RIGHT_OUTER_JOIN 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/MyStaging/MyStaging.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net6.0 4 | ron.liang 5 | lianggx@foxmail.com 6 | true 7 | 这是一个 .netcore的脚手架,支持DbFirst和CodeFirst,让开发人员无需关注底层变动,专注编写业务代码,它可以让你使用 .netcore的新特性,支持多种数据库,可以在项目中自由的使用 lambda 表达式编写业务,同时支持自定义的 sql 语句。 8 | MIT 9 | 10 | https://github.com/lianggx/mystaging 11 | 3.0.9 12 | 全新架构改动,支持多库/多路上下文,支持 DbFirst/CodeFirst。旧版本请使用2.1.10版本。 13 | true 14 | LICENSE 15 | 16 | 17 | 18 | bin\Debug\netstandard2.0\MyStaging.xml 19 | 1701;1702;1591;IDE0060 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | True 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /src/MyStaging/MyStaging.csproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | false 5 | 6 | -------------------------------------------------------------------------------- /test/MyStaging.xUnitTest.db/DAL/Build/Article.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.Helpers; 2 | using MyStaging.PostgreSQL; 3 | using MyStaging.xUnitTest.Model; 4 | using Newtonsoft.Json.Linq; 5 | using NpgsqlTypes; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq.Expressions; 9 | 10 | namespace MyStaging.xUnitTest.DAL 11 | { 12 | public partial class Article : PgDbContext 13 | { 14 | public static Article Context { get { return new Article(); } } 15 | 16 | public static InsertBuilder InsertBuilder => new InsertBuilder(); 17 | public static ArticleModel Insert(ArticleModel model) => InsertBuilder.Insert(model); 18 | public static int InsertRange(List models) => InsertBuilder.InsertRange(models).SaveChange(); 19 | 20 | public static DeleteBuilder DeleteBuilder => new DeleteBuilder(); 21 | public static int Delete(string id, string userid) 22 | { 23 | var affrows = DeleteBuilder.Where(f => f.Id == id && f.Userid == userid).SaveChange(); 24 | if (affrows > 0) ContextManager.CacheManager?.RemoveItemCache(id + "" + userid); 25 | return affrows; 26 | } 27 | 28 | public static ArticleUpdateBuilder UpdateBuilder => new ArticleUpdateBuilder(); 29 | public static ArticleUpdateBuilder Update(string id, string userid) 30 | { 31 | return new ArticleUpdateBuilder(null, id, userid); 32 | } 33 | 34 | public class ArticleUpdateBuilder : UpdateBuilder 35 | { 36 | public ArticleUpdateBuilder(string id, string userid) 37 | { 38 | base.Where(f => f.Id == id && f.Userid == userid); 39 | } 40 | 41 | public ArticleUpdateBuilder(Action onChanged, string id, string userid) : base(onChanged) 42 | { 43 | base.Where(f => f.Id == id && f.Userid == userid); 44 | } 45 | 46 | public ArticleUpdateBuilder() { } 47 | 48 | public new ArticleUpdateBuilder Where(Expression> predicate) 49 | { 50 | base.Where(predicate); 51 | return this; 52 | } 53 | public new ArticleUpdateBuilder Where(string expression) 54 | { 55 | base.Where(expression); 56 | return this; 57 | } 58 | public ArticleUpdateBuilder SetId(string id) 59 | { 60 | base.SetField("id", id); 61 | return this; 62 | } 63 | public ArticleUpdateBuilder SetUserid(string userid) 64 | { 65 | base.SetField("userid", userid); 66 | return this; 67 | } 68 | public ArticleUpdateBuilder SetTitle(string title) 69 | { 70 | base.SetField("title", title); 71 | return this; 72 | } 73 | public ArticleUpdateBuilder SetContent(JToken content) 74 | { 75 | base.SetField("content", content); 76 | return this; 77 | } 78 | public ArticleUpdateBuilder SetCreatetime(DateTime createtime) 79 | { 80 | base.SetField("createtime", createtime); 81 | return this; 82 | } 83 | } 84 | 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /test/MyStaging.xUnitTest.db/DAL/Build/Post.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.Helpers; 2 | using MyStaging.PostgreSQL; 3 | using MyStaging.xUnitTest.Model; 4 | using Newtonsoft.Json.Linq; 5 | using NpgsqlTypes; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq.Expressions; 9 | 10 | namespace MyStaging.xUnitTest.DAL 11 | { 12 | public partial class Post : PgDbContext 13 | { 14 | public static Post Context { get { return new Post(); } } 15 | 16 | public static InsertBuilder InsertBuilder => new InsertBuilder(); 17 | public static PostModel Insert(PostModel model) => InsertBuilder.Insert(model); 18 | public static int InsertRange(List models) => InsertBuilder.InsertRange(models).SaveChange(); 19 | 20 | public static DeleteBuilder DeleteBuilder => new DeleteBuilder(); 21 | public static int Delete(Guid id) 22 | { 23 | var affrows = DeleteBuilder.Where(f => f.Id == id).SaveChange(); 24 | if (affrows > 0) ContextManager.CacheManager?.RemoveItemCache(id.ToString()); 25 | return affrows; 26 | } 27 | 28 | public static PostUpdateBuilder UpdateBuilder => new PostUpdateBuilder(); 29 | public static PostUpdateBuilder Update(Guid id) 30 | { 31 | return new PostUpdateBuilder(null, id); 32 | } 33 | 34 | public class PostUpdateBuilder : UpdateBuilder 35 | { 36 | public PostUpdateBuilder(Guid id) 37 | { 38 | base.Where(f => f.Id == id); 39 | } 40 | 41 | public PostUpdateBuilder(Action onChanged, Guid id) : base(onChanged) 42 | { 43 | base.Where(f => f.Id == id); 44 | } 45 | 46 | public PostUpdateBuilder() { } 47 | 48 | public new PostUpdateBuilder Where(Expression> predicate) 49 | { 50 | base.Where(predicate); 51 | return this; 52 | } 53 | public new PostUpdateBuilder Where(string expression) 54 | { 55 | base.Where(expression); 56 | return this; 57 | } 58 | public PostUpdateBuilder SetId(Guid id) 59 | { 60 | base.SetField("id", id); 61 | return this; 62 | } 63 | public PostUpdateBuilder SetTitle(string title) 64 | { 65 | base.SetField("title", title); 66 | return this; 67 | } 68 | public PostUpdateBuilder SetContent(JToken content) 69 | { 70 | base.SetField("content", content); 71 | return this; 72 | } 73 | public PostUpdateBuilder SetState(Et_data_state? state) 74 | { 75 | base.SetField("state", state); 76 | return this; 77 | } 78 | public PostUpdateBuilder SetRole(Et_role? role) 79 | { 80 | base.SetField("role", role); 81 | return this; 82 | } 83 | public PostUpdateBuilder SetText(JToken text) 84 | { 85 | base.SetField("text", text); 86 | return this; 87 | } 88 | } 89 | 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /test/MyStaging.xUnitTest.db/DAL/Build/Topic.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.Helpers; 2 | using MyStaging.PostgreSQL; 3 | using MyStaging.xUnitTest.Model; 4 | using NpgsqlTypes; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq.Expressions; 8 | 9 | namespace MyStaging.xUnitTest.DAL 10 | { 11 | public partial class Topic : PgDbContext 12 | { 13 | public static Topic Context { get { return new Topic(); } } 14 | 15 | public static InsertBuilder InsertBuilder => new InsertBuilder(); 16 | public static TopicModel Insert(TopicModel model) => InsertBuilder.Insert(model); 17 | public static int InsertRange(List models) => InsertBuilder.InsertRange(models).SaveChange(); 18 | 19 | public static DeleteBuilder DeleteBuilder => new DeleteBuilder(); 20 | public static int Delete(Guid id) 21 | { 22 | var affrows = DeleteBuilder.Where(f => f.Id == id).SaveChange(); 23 | if (affrows > 0) ContextManager.CacheManager?.RemoveItemCache(id.ToString()); 24 | return affrows; 25 | } 26 | 27 | public static TopicUpdateBuilder UpdateBuilder => new TopicUpdateBuilder(); 28 | public static TopicUpdateBuilder Update(Guid id) 29 | { 30 | return new TopicUpdateBuilder(null, id); 31 | } 32 | 33 | public class TopicUpdateBuilder : UpdateBuilder 34 | { 35 | public TopicUpdateBuilder(Guid id) 36 | { 37 | base.Where(f => f.Id == id); 38 | } 39 | 40 | public TopicUpdateBuilder(Action onChanged, Guid id) : base(onChanged) 41 | { 42 | base.Where(f => f.Id == id); 43 | } 44 | 45 | public TopicUpdateBuilder() { } 46 | 47 | public new TopicUpdateBuilder Where(Expression> predicate) 48 | { 49 | base.Where(predicate); 50 | return this; 51 | } 52 | public new TopicUpdateBuilder Where(string expression) 53 | { 54 | base.Where(expression); 55 | return this; 56 | } 57 | public TopicUpdateBuilder SetId(Guid id) 58 | { 59 | base.SetField("id", id); 60 | return this; 61 | } 62 | public TopicUpdateBuilder SetTitle(string title) 63 | { 64 | base.SetField("title", title); 65 | return this; 66 | } 67 | public TopicUpdateBuilder SetCreate_time(DateTime? create_time) 68 | { 69 | base.SetField("create_time", create_time); 70 | return this; 71 | } 72 | public TopicUpdateBuilder SetUpdate_time(DateTime? update_time) 73 | { 74 | base.SetField("update_time", update_time); 75 | return this; 76 | } 77 | public TopicUpdateBuilder SetLast_time(DateTime? last_time) 78 | { 79 | base.SetField("last_time", last_time); 80 | return this; 81 | } 82 | public TopicUpdateBuilder SetUser_id(Guid? user_id) 83 | { 84 | base.SetField("user_id", user_id); 85 | return this; 86 | } 87 | public TopicUpdateBuilder SetName(string name) 88 | { 89 | base.SetField("name", name); 90 | return this; 91 | } 92 | public TopicUpdateBuilder SetAge(int? age) 93 | { 94 | base.SetField("age", age); 95 | return this; 96 | } 97 | public TopicUpdateBuilder SetSex(bool? sex) 98 | { 99 | base.SetField("sex", sex); 100 | return this; 101 | } 102 | public TopicUpdateBuilder SetCreatetime(DateTime? createtime) 103 | { 104 | base.SetField("createtime", createtime); 105 | return this; 106 | } 107 | public TopicUpdateBuilder SetUpdatetime(TimeSpan? updatetime) 108 | { 109 | base.SetField("updatetime", updatetime); 110 | return this; 111 | } 112 | } 113 | 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /test/MyStaging.xUnitTest.db/DAL/Build/User.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.Helpers; 2 | using MyStaging.PostgreSQL; 3 | using MyStaging.xUnitTest.Model; 4 | using NpgsqlTypes; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq.Expressions; 8 | 9 | namespace MyStaging.xUnitTest.DAL 10 | { 11 | public partial class User : PgDbContext 12 | { 13 | public static User Context { get { return new User(); } } 14 | 15 | public static InsertBuilder InsertBuilder => new InsertBuilder(); 16 | public static UserModel Insert(UserModel model) => InsertBuilder.Insert(model); 17 | public static int InsertRange(List models) => InsertBuilder.InsertRange(models).SaveChange(); 18 | 19 | public static DeleteBuilder DeleteBuilder => new DeleteBuilder(); 20 | public static int Delete(string id) 21 | { 22 | var affrows = DeleteBuilder.Where(f => f.Id == id).SaveChange(); 23 | if (affrows > 0) ContextManager.CacheManager?.RemoveItemCache(id); 24 | return affrows; 25 | } 26 | 27 | public static UserUpdateBuilder UpdateBuilder => new UserUpdateBuilder(); 28 | public static UserUpdateBuilder Update(string id) 29 | { 30 | return new UserUpdateBuilder(null, id); 31 | } 32 | 33 | public class UserUpdateBuilder : UpdateBuilder 34 | { 35 | public UserUpdateBuilder(string id) 36 | { 37 | base.Where(f => f.Id == id); 38 | } 39 | 40 | public UserUpdateBuilder(Action onChanged, string id) : base(onChanged) 41 | { 42 | base.Where(f => f.Id == id); 43 | } 44 | 45 | public UserUpdateBuilder() { } 46 | 47 | public new UserUpdateBuilder Where(Expression> predicate) 48 | { 49 | base.Where(predicate); 50 | return this; 51 | } 52 | public new UserUpdateBuilder Where(string expression) 53 | { 54 | base.Where(expression); 55 | return this; 56 | } 57 | public UserUpdateBuilder SetId(string id) 58 | { 59 | base.SetField("id", id); 60 | return this; 61 | } 62 | public UserUpdateBuilder SetLoginname(string loginname) 63 | { 64 | base.SetField("loginname", loginname); 65 | return this; 66 | } 67 | public UserUpdateBuilder SetPassword(string password) 68 | { 69 | base.SetField("password", password); 70 | return this; 71 | } 72 | public UserUpdateBuilder SetNickname(string nickname) 73 | { 74 | base.SetField("nickname", nickname); 75 | return this; 76 | } 77 | public UserUpdateBuilder SetSex(bool? sex) 78 | { 79 | base.SetField("sex", sex); 80 | return this; 81 | } 82 | public UserUpdateBuilder SetAge(int age) 83 | { 84 | base.SetField("age", age); 85 | return this; 86 | } 87 | public UserUpdateBuilder SetMoney(decimal money) 88 | { 89 | base.SetField("money", money); 90 | return this; 91 | } 92 | public UserUpdateBuilder SetCreatetime(DateTime createtime) 93 | { 94 | base.SetField("createtime", createtime); 95 | return this; 96 | } 97 | public UserUpdateBuilder SetWealth(decimal wealth) 98 | { 99 | base.SetField("wealth", wealth); 100 | return this; 101 | } 102 | public UserUpdateBuilder SetRole(Et_role? role) 103 | { 104 | base.SetField("role", role); 105 | return this; 106 | } 107 | } 108 | 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /test/MyStaging.xUnitTest.db/Model/Build/ArticleModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using MyStaging.xUnitTest.DAL; 4 | using Newtonsoft.Json; 5 | using Newtonsoft.Json.Linq; 6 | using MyStaging.Mapping; 7 | using NpgsqlTypes; 8 | using MyStaging.Helpers; 9 | 10 | namespace MyStaging.xUnitTest.Model 11 | { 12 | [EntityMapping(name: "article", Schema = "public")] 13 | public partial class ArticleModel 14 | { 15 | [PrimaryKey] 16 | public string Id { get; set; } 17 | 18 | [PrimaryKey] 19 | public string Userid { get; set; } 20 | 21 | public string Title { get; set; } 22 | 23 | public JToken Content { get; set; } 24 | 25 | public DateTime Createtime { get; set; } 26 | 27 | private UserModel user = null; 28 | [ForeignKeyMapping(name: "userid"), JsonIgnore] public UserModel User { get { if (user == null) user = MyStaging.xUnitTest.DAL.User.Context.Where(f => f.Id == this.Userid).ToOne(); return user; } } 29 | 30 | [NonDbColumnMapping, JsonIgnore] public MyStaging.xUnitTest.DAL.Article.ArticleUpdateBuilder UpdateBuilder { get { return new MyStaging.xUnitTest.DAL.Article.ArticleUpdateBuilder(model =>{MyStaging.Helpers.MyStagingUtils.CopyProperty(this, model); ContextManager.CacheManager?.RemoveItemCache(this.Id + "" + this.Userid); }, this.Id,this.Userid); } } 31 | 32 | public ArticleModel Insert() { return MyStaging.xUnitTest.DAL.Article.Insert(this); } 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /test/MyStaging.xUnitTest.db/Model/Build/PostModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using MyStaging.xUnitTest.DAL; 4 | using Newtonsoft.Json; 5 | using Newtonsoft.Json.Linq; 6 | using MyStaging.Mapping; 7 | using NpgsqlTypes; 8 | using MyStaging.Helpers; 9 | 10 | namespace MyStaging.xUnitTest.Model 11 | { 12 | [EntityMapping(name: "post", Schema = "public")] 13 | public partial class PostModel 14 | { 15 | [PrimaryKey] 16 | public Guid Id { get; set; } 17 | 18 | public string Title { get; set; } 19 | 20 | public JToken Content { get; set; } 21 | 22 | public Et_data_state? State { get; set; } 23 | 24 | public Et_role? Role { get; set; } 25 | 26 | public JToken Text { get; set; } 27 | 28 | [NonDbColumnMapping, JsonIgnore] public MyStaging.xUnitTest.DAL.Post.PostUpdateBuilder UpdateBuilder { get { return new MyStaging.xUnitTest.DAL.Post.PostUpdateBuilder(model =>{MyStaging.Helpers.MyStagingUtils.CopyProperty(this, model); ContextManager.CacheManager?.RemoveItemCache(this.Id.ToString()); }, this.Id); } } 29 | 30 | public PostModel Insert() { return MyStaging.xUnitTest.DAL.Post.Insert(this); } 31 | 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test/MyStaging.xUnitTest.db/Model/Build/TopicModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using MyStaging.xUnitTest.DAL; 4 | using Newtonsoft.Json; 5 | using Newtonsoft.Json.Linq; 6 | using MyStaging.Mapping; 7 | using NpgsqlTypes; 8 | using MyStaging.Helpers; 9 | 10 | namespace MyStaging.xUnitTest.Model 11 | { 12 | [EntityMapping(name: "topic", Schema = "public")] 13 | public partial class TopicModel 14 | { 15 | [PrimaryKey] 16 | public Guid Id { get; set; } 17 | 18 | public string Title { get; set; } 19 | 20 | public DateTime? Create_time { get; set; } 21 | 22 | public DateTime? Update_time { get; set; } 23 | 24 | public DateTime? Last_time { get; set; } 25 | 26 | public Guid? User_id { get; set; } 27 | 28 | public string Name { get; set; } 29 | 30 | public int? Age { get; set; } 31 | 32 | public bool? Sex { get; set; } 33 | 34 | public DateTime? Createtime { get; set; } 35 | 36 | public TimeSpan? Updatetime { get; set; } 37 | 38 | [NonDbColumnMapping, JsonIgnore] public MyStaging.xUnitTest.DAL.Topic.TopicUpdateBuilder UpdateBuilder { get { return new MyStaging.xUnitTest.DAL.Topic.TopicUpdateBuilder(model =>{MyStaging.Helpers.MyStagingUtils.CopyProperty(this, model); ContextManager.CacheManager?.RemoveItemCache(this.Id.ToString()); }, this.Id); } } 39 | 40 | public TopicModel Insert() { return MyStaging.xUnitTest.DAL.Topic.Insert(this); } 41 | 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /test/MyStaging.xUnitTest.db/Model/Build/UserModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using MyStaging.xUnitTest.DAL; 4 | using Newtonsoft.Json; 5 | using Newtonsoft.Json.Linq; 6 | using MyStaging.Mapping; 7 | using NpgsqlTypes; 8 | using MyStaging.Helpers; 9 | 10 | namespace MyStaging.xUnitTest.Model 11 | { 12 | [EntityMapping(name: "user", Schema = "public")] 13 | public partial class UserModel 14 | { 15 | [PrimaryKey] 16 | public string Id { get; set; } 17 | 18 | public string Loginname { get; set; } 19 | 20 | public string Password { get; set; } 21 | 22 | public string Nickname { get; set; } 23 | 24 | public bool? Sex { get; set; } 25 | 26 | public int Age { get; set; } 27 | 28 | public decimal Money { get; set; } 29 | 30 | public DateTime Createtime { get; set; } 31 | 32 | public decimal Wealth { get; set; } 33 | 34 | [NonDbColumnMapping, JsonIgnore] public MyStaging.xUnitTest.DAL.User.UserUpdateBuilder UpdateBuilder { get { return new MyStaging.xUnitTest.DAL.User.UserUpdateBuilder(model =>{MyStaging.Helpers.MyStagingUtils.CopyProperty(this, model); ContextManager.CacheManager?.RemoveItemCache(this.Id); }, this.Id); } } 35 | 36 | public UserModel Insert() { return MyStaging.xUnitTest.DAL.User.Insert(this); } 37 | 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /test/MyStaging.xUnitTest.db/Model/Build/_Enums.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MyStaging.xUnitTest.Model 4 | { 5 | public enum Et_data_state 6 | { 7 | 正常, 8 | 删除, 9 | } 10 | public enum Et_role 11 | { 12 | 管理员, 13 | 普通成员, 14 | 群主, 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /test/MyStaging.xUnitTest.db/MyStaging.xUnitTest.db.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | netstandard2.1 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /test/MyStaging.xUnitTest.db/_startup.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.xUnitTest.Model; 2 | using System; 3 | using Npgsql; 4 | using Microsoft.Extensions.Logging; 5 | using MyStaging.Helpers; 6 | using MyStaging.Common; 7 | using Newtonsoft.Json.Linq; 8 | using Microsoft.Extensions.Caching.Distributed; 9 | 10 | namespace MyStaging.xUnitTest 11 | { 12 | public class _startup 13 | { 14 | public static void Init(StagingOptions options) 15 | { 16 | ContextManager.InitConnection(options); 17 | 18 | Type[] jsonTypes = { typeof(JToken), typeof(JObject), typeof(JArray) }; 19 | NpgsqlNameTranslator translator = new NpgsqlNameTranslator(); 20 | NpgsqlConnection.GlobalTypeMapper.UseJsonNet(jsonTypes); 21 | 22 | NpgsqlConnection.GlobalTypeMapper.MapEnum("public.et_data_state", translator); 23 | NpgsqlConnection.GlobalTypeMapper.MapEnum("public.et_role", translator); 24 | } 25 | } 26 | public partial class NpgsqlNameTranslator : INpgsqlNameTranslator 27 | { 28 | public string TranslateMemberName(string clrName) => clrName; 29 | public string TranslateTypeName(string clrTypeName) => clrTypeName; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /test/MyStaging.xUnitTest/Common/CheckNotNullTest.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.xUnitTest.Models; 2 | using Xunit; 3 | 4 | namespace MyStaging.Common 5 | { 6 | public class CheckNotNullTest 7 | { 8 | [Fact] 9 | public void NotNull() 10 | { 11 | var user = new UserModel { Id = 1 }; 12 | CheckNotNull.NotNull(user, nameof(user)); 13 | 14 | user = null; 15 | CheckNotNull.NotNull(user, nameof(user)); 16 | } 17 | 18 | [Fact] 19 | public void NotEmpty() 20 | { 21 | var name = string.Empty; 22 | CheckNotNull.NotEmpty(name, nameof(name)); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /test/MyStaging.xUnitTest/Common/MyStagingUtilsTest.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.Common; 2 | using MyStaging.Metadata; 3 | using MyStaging.xUnitTest.Models; 4 | using Xunit; 5 | 6 | namespace MyStaging.xUnitTest.Common 7 | { 8 | public class MyStagingUtilsTest 9 | { 10 | [Fact] 11 | public void GetDbFields() 12 | { 13 | var pis = MyStagingUtils.GetDbFields(typeof(UserModel)); 14 | Assert.Equal(10, pis.Count); 15 | } 16 | 17 | [Fact] 18 | public void GetMapping() 19 | { 20 | var mysqlName = "`mystaging`.`user`"; 21 | var mysql = MyStagingUtils.GetMapping(typeof(UserModel), Metadata.ProviderType.MySql); 22 | Assert.Equal(mysqlName, mysql); 23 | 24 | var pgsqlName = "\"mystaging\".\"user\""; 25 | var pgsql = MyStagingUtils.GetMapping(typeof(UserModel), Metadata.ProviderType.PostgreSQL); 26 | Assert.Equal(pgsqlName, pgsql); 27 | } 28 | 29 | [Fact] 30 | public void GetTableName() 31 | { 32 | var table = new TableInfo 33 | { 34 | Schema = "mystaging", 35 | Name = "user" 36 | }; 37 | var mysqlName = "`mystaging`.`user`"; 38 | var mysql = MyStagingUtils.GetTableName(table, Metadata.ProviderType.MySql); 39 | Assert.Equal(mysqlName, mysql); 40 | 41 | var pgsqlName = "\"mystaging\".\"user\""; 42 | var pgsql = MyStagingUtils.GetTableName(table, Metadata.ProviderType.PostgreSQL); 43 | Assert.Equal(pgsqlName, pgsql); 44 | } 45 | 46 | [Fact] 47 | public void CopyProperty() 48 | { 49 | var source = new UserModel 50 | { 51 | Id = 1, 52 | Age = 18, 53 | }; 54 | UserModel target = new UserModel(); 55 | MyStagingUtils.CopyProperty(target, source); 56 | Assert.Equal(source.Id, target.Id); 57 | } 58 | 59 | [Fact] 60 | public void GetValueTuple() 61 | { 62 | 63 | } 64 | 65 | [Fact] 66 | public void GetMemberName() 67 | { 68 | var source = new UserModel 69 | { 70 | Id = 1, 71 | Age = 18, 72 | }; 73 | UserModel target = new UserModel(); 74 | var memberName = MyStagingUtils.GetMemberName(f => f.Id); 75 | Assert.Equal("Id", memberName); 76 | } 77 | 78 | [Fact] 79 | public void ToUpperPascal() 80 | { 81 | var field = "Name"; 82 | var cast = MyStagingUtils.ToUpperPascal("name"); 83 | Assert.Equal(field, cast); 84 | } 85 | 86 | [Fact] 87 | public void ToLowerPascal() 88 | { 89 | var field = "name"; 90 | var cast = MyStagingUtils.ToLowerPascal("Name"); 91 | Assert.Equal(field, cast); 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /test/MyStaging.xUnitTest/ConstantUtil.cs: -------------------------------------------------------------------------------- 1 | namespace MyStaging.xUnitTest 2 | { 3 | public class ConstantUtil 4 | { 5 | public static string PGSQL_CONNECTION = "Host=127.0.0.1;Port=5432;Username=postgres;Password=postgres;Database=mystaging;Pooling=true;Maximum Pool Size=1000;Timeout=10;CommandTimeout=120;"; 6 | 7 | public static string MYSQL_CONNECTION = "server=127.0.0.1;user id=root;password=root;database=mystaging"; 8 | 9 | public readonly static string REDIS_CONNECTION = "127.0.0.1:6379,defaultDatabase=1,name=mystaging,prefix=mystaging,abortConnect=false"; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /test/MyStaging.xUnitTest/Core/ConnectionManagerTest.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.Core; 2 | using Xunit; 3 | 4 | namespace MyStaging.xUnitTest.Core 5 | { 6 | public class ConnectionManagerTest 7 | { 8 | [Fact] 9 | public void Add() 10 | { 11 | ConnectionManager.Add("mysql", ConstantUtil.PGSQL_CONNECTION, false); 12 | ConnectionManager.Add("mysql", ConstantUtil.PGSQL_CONNECTION, true); 13 | } 14 | 15 | [Fact] 16 | public void Get() 17 | { 18 | Add(); 19 | var masterCM = ConnectionManager.Get("mysql", false); 20 | var slaveCM = ConnectionManager.Get("mysql", true); 21 | 22 | Assert.Equal(masterCM.ConnectionString, ConstantUtil.PGSQL_CONNECTION); 23 | Assert.Equal(slaveCM.ConnectionString, ConstantUtil.PGSQL_CONNECTION); 24 | } 25 | 26 | [Fact] 27 | public void Remove() 28 | { 29 | Add(); 30 | ConnectionManager.Remove("mysql"); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test/MyStaging.xUnitTest/Core/DbContextTest.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.Core; 2 | using MyStaging.Metadata; 3 | using MyStaging.xUnitTest.Models; 4 | using Xunit; 5 | 6 | namespace MyStaging.xUnitTest.Core 7 | { 8 | public class MySqlDbContext : DbContext 9 | { 10 | public MySqlDbContext(StagingOptions options) : base(options, ProviderType.MySql) 11 | { 12 | } 13 | 14 | public DbSet User { get; set; } 15 | } 16 | 17 | public class DbContextTest 18 | { 19 | [Fact] 20 | public void Init() 21 | { 22 | var options = new MyStaging.Metadata.StagingOptions("MySql", ConstantUtil.MYSQL_CONNECTION); 23 | var context = new MySqlDbContext(options); 24 | 25 | Assert.NotNull(context.User); 26 | } 27 | 28 | [Fact] 29 | public void Refresh() 30 | { 31 | var options = new MyStaging.Metadata.StagingOptions("MySql", ConstantUtil.MYSQL_CONNECTION); 32 | var context = new MySqlDbContext(options); 33 | context.Refresh(ConstantUtil.MYSQL_CONNECTION, null); 34 | 35 | Assert.NotNull(context.User); 36 | } 37 | 38 | [Fact] 39 | public void Transaction() 40 | { 41 | var options = new MyStaging.Metadata.StagingOptions("MySql", ConstantUtil.MYSQL_CONNECTION); 42 | var context = new MySqlDbContext(options); 43 | context.BeginTransaction(); 44 | Assert.Single(context.Trans); 45 | context.CommitTransaction(); 46 | Assert.Equal(0, context.Trans.Keys.Count); 47 | 48 | context.BeginTransaction(); 49 | Assert.Single(context.Trans); 50 | context.RollBackTransaction(); 51 | Assert.Equal(0, context.Trans.Keys.Count); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /test/MyStaging.xUnitTest/Core/DbExpressionVisitorTest.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.Core; 2 | using MyStaging.xUnitTest.Models; 3 | using System; 4 | using System.Linq.Expressions; 5 | using Xunit; 6 | using Xunit.Abstractions; 7 | 8 | namespace MyStaging.xUnitTest.Core 9 | { 10 | public class DbExpressionVisitorTest 11 | { 12 | private readonly ITestOutputHelper testOutput; 13 | public DbExpressionVisitorTest(ITestOutputHelper testOutput) 14 | { 15 | this.testOutput = testOutput; 16 | } 17 | 18 | [Fact] 19 | public void Visit() 20 | { 21 | var options = new MyStaging.Metadata.StagingOptions("MySql", ConstantUtil.MYSQL_CONNECTION); 22 | var context = new MySqlDbContext(options); 23 | 24 | Expression> predicate = (f) => f.Id == 1; 25 | DbExpressionVisitor exp = new DbExpressionVisitor 26 | { 27 | TypeMaster = typeof(UserModel), 28 | AliasMaster = "a", 29 | AliasUnion = null 30 | }; 31 | 32 | exp.Visit(predicate); 33 | var sql = exp.SqlText.Builder.ToString(); 34 | testOutput.WriteLine(sql); 35 | 36 | Assert.StartsWith("(a.Id = @", sql); 37 | var count = exp.SqlText.Parameters.Count; 38 | Assert.Equal(1, count); 39 | 40 | predicate = (f) => f.Id == 1 && f.IP == "127.0.0.1"; 41 | exp = new DbExpressionVisitor 42 | { 43 | TypeMaster = typeof(UserModel), 44 | AliasMaster = "a", 45 | AliasUnion = null 46 | }; 47 | 48 | exp.Visit(predicate); 49 | sql = exp.SqlText.Builder.ToString(); 50 | testOutput.WriteLine(sql); 51 | 52 | Assert.StartsWith("((a.Id = @", sql); 53 | Assert.EndsWith("))", sql); 54 | count = exp.SqlText.Parameters.Count; 55 | Assert.Equal(2, count); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /test/MyStaging.xUnitTest/Core/SQLExecuteTest.cs: -------------------------------------------------------------------------------- 1 | namespace MyStaging.xUnitTest.Core 2 | { 3 | public class SQLExecuteTest 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /test/MyStaging.xUnitTest/Models/UserModel.cs: -------------------------------------------------------------------------------- 1 | using MyStaging.DataAnnotations; 2 | using System; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | 5 | namespace MyStaging.xUnitTest.Models 6 | { 7 | [Table(name: "user", Schema = "mystaging")] 8 | public partial class UserModel 9 | { 10 | [PrimaryKey] 11 | public int Id { get; set; } 12 | public string LoginName { get; set; } 13 | public string Password { get; set; } 14 | public string Nickname { get; set; } 15 | public bool? Sex { get; set; } 16 | public int Age { get; set; } 17 | public decimal Money { get; set; } 18 | public DateTime CreateTime { get; set; } 19 | public decimal Wealth { get; set; } 20 | public string IP { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /test/MyStaging.xUnitTest/MyStaging.xUnitTest.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net6.0 5 | false 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | all 15 | runtime; build; native; contentfiles; analyzers; buildtransitive 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /test/MyStaging.xUnitTest/MyStaging.xUnitTest.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio 15> 3 | VisualStudioVersion = 15.0.26430.13 4 | Project("1257b8c1-0b30-4662-a424-584e41ed92c3") = "MyStaging.xUnitTest.db", "MyStaging.xUnitTest.db\MyStaging.xUnitTest.db.csproj", "8e062aae-bdd0-4d31-99cd-9b3a4f7979e9" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Any CPU = Debug|Any CPU 9 | Release|Any CPU = Release|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | 8e062aae-bdd0-4d31-99cd-9b3a4f7979e9.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | 8e062aae-bdd0-4d31-99cd-9b3a4f7979e9.Debug|Any CPU.Build.0 = Debug|Any CPU 14 | 8e062aae-bdd0-4d31-99cd-9b3a4f7979e9.Release|Any CPU.ActiveCfg = Release|Any CPU 15 | 8e062aae-bdd0-4d31-99cd-9b3a4f7979e9.Release|Any CPU.Build.0 = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | --------------------------------------------------------------------------------