├── .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