Browse Source

添加项目文件。

master
faker 2 years ago
commit
e5e181488d
  1. 25
      .dockerignore
  2. 63
      .gitattributes
  3. 316
      .gitignore
  4. 30
      Dockerfile
  5. 21
      LICENSE
  6. 804
      Znyc.Cloudcar.Admin.AspNetCore/AspNetCore.xml
  7. 49
      Znyc.Cloudcar.Admin.AspNetCore/Common/CorsMiddleware.cs
  8. 115
      Znyc.Cloudcar.Admin.AspNetCore/Common/ErrCode.cs
  9. 25
      Znyc.Cloudcar.Admin.AspNetCore/Common/Initialization.cs
  10. 93
      Znyc.Cloudcar.Admin.AspNetCore/Common/MyApiException.cs
  11. 64
      Znyc.Cloudcar.Admin.AspNetCore/Common/Permission.cs
  12. 20
      Znyc.Cloudcar.Admin.AspNetCore/Common/SessionObject.cs
  13. 253
      Znyc.Cloudcar.Admin.AspNetCore/Mvc/ApiController.cs
  14. 373
      Znyc.Cloudcar.Admin.AspNetCore/Mvc/AreaApiController.cs
  15. 149
      Znyc.Cloudcar.Admin.AspNetCore/Mvc/Filter/ActionFilter.cs
  16. 102
      Znyc.Cloudcar.Admin.AspNetCore/Mvc/Filter/ExceptionHandlingAttribute.cs
  17. 74
      Znyc.Cloudcar.Admin.AspNetCore/Mvc/Filter/FunctionAuthorizationFilter.cs
  18. 26
      Znyc.Cloudcar.Admin.AspNetCore/Mvc/Filter/FunctionAuthorizeAttribute.cs
  19. 49
      Znyc.Cloudcar.Admin.AspNetCore/Mvc/Filter/HiddenApiAttribute.cs
  20. 18
      Znyc.Cloudcar.Admin.AspNetCore/Mvc/Filter/NoPermissionRequiredAttribute.cs
  21. 55
      Znyc.Cloudcar.Admin.AspNetCore/Mvc/Filter/SwaggerFileUploadFilter.cs
  22. 220
      Znyc.Cloudcar.Admin.AspNetCore/Mvc/TokenProvider.cs
  23. 16
      Znyc.Cloudcar.Admin.AspNetCore/Properties/PublishProfiles/FolderProfile.pubxml
  24. 24
      Znyc.Cloudcar.Admin.AspNetCore/ViewModel/DBConnResult.cs
  25. 48
      Znyc.Cloudcar.Admin.AspNetCore/ViewModel/DbConnInfo.cs
  26. 34
      Znyc.Cloudcar.Admin.AspNetCore/ViewModel/SearchModel.cs
  27. 22
      Znyc.Cloudcar.Admin.AspNetCore/ViewModel/UpdateEnableViewModel.cs
  28. 27
      Znyc.Cloudcar.Admin.AspNetCore/ViewModel/VueCascaderModel.cs
  29. 90
      Znyc.Cloudcar.Admin.AspNetCore/ViewModel/VuexMenusTree.cs
  30. 73
      Znyc.Cloudcar.Admin.AspNetCore/Znyc.Cloudcar.Admin.AspNetCore.csproj
  31. 23
      Znyc.Cloudcar.Admin.Commons/Attributes/AppDbContextFactoryAttribute.cs
  32. 39
      Znyc.Cloudcar.Admin.Commons/Attributes/ShardingTableAttribute.cs
  33. 12
      Znyc.Cloudcar.Admin.Commons/Attributes/UnitOfWorkAttribute.cs
  34. 406
      Znyc.Cloudcar.Admin.Commons/Cache/CacheHelper.cs
  35. 23
      Znyc.Cloudcar.Admin.Commons/Cache/CacheProvider.cs
  36. 305
      Znyc.Cloudcar.Admin.Commons/Cache/ICacheService.cs
  37. 594
      Znyc.Cloudcar.Admin.Commons/Cache/MemoryCacheService.cs
  38. 634
      Znyc.Cloudcar.Admin.Commons/Cache/RedisCacheService.cs
  39. 235
      Znyc.Cloudcar.Admin.Commons/Commons.csproj
  40. 49
      Znyc.Cloudcar.Admin.Commons/Config/Configs.cs
  41. 79
      Znyc.Cloudcar.Admin.Commons/Const/CommonConst.cs
  42. 90
      Znyc.Cloudcar.Admin.Commons/Const/CurrencyConst.cs
  43. 115
      Znyc.Cloudcar.Admin.Commons/Const/ReturnConst.cs
  44. 289
      Znyc.Cloudcar.Admin.Commons/Core/App/App.cs
  45. 32
      Znyc.Cloudcar.Admin.Commons/Core/App/HostingStartup.cs
  46. 69
      Znyc.Cloudcar.Admin.Commons/Core/App/HttpContextLocal.cs
  47. 461
      Znyc.Cloudcar.Admin.Commons/Core/Application/BaseApp.cs
  48. 128
      Znyc.Cloudcar.Admin.Commons/Core/Dapper/DapperDbContext.cs
  49. 24
      Znyc.Cloudcar.Admin.Commons/Core/DataManager/AppDBContextAttribute.cs
  50. 230
      Znyc.Cloudcar.Admin.Commons/Core/DataManager/DBServerProvider.cs
  51. 42
      Znyc.Cloudcar.Admin.Commons/Core/DataManager/DbConnectionOptions.cs
  52. 23
      Znyc.Cloudcar.Admin.Commons/Core/DataManager/WriteAndReadEnum.cs
  53. 18
      Znyc.Cloudcar.Admin.Commons/Core/DataManager/YuebonDbOptions.cs
  54. 64
      Znyc.Cloudcar.Admin.Commons/Core/DataManager/YuebonDbOptionsSetup.cs
  55. 796
      Znyc.Cloudcar.Admin.Commons/Core/DbContextCore/BaseDbContext.cs
  56. 101
      Znyc.Cloudcar.Admin.Commons/Core/DbContextCore/DbContextFactory.cs
  57. 17
      Znyc.Cloudcar.Admin.Commons/Core/DbContextCore/DefaultModelBuilder.cs
  58. 124
      Znyc.Cloudcar.Admin.Commons/Core/DbContextCore/MySqlDbContext.cs
  59. 69
      Znyc.Cloudcar.Admin.Commons/Core/DbContextCore/OracleDbContext.cs
  60. 80
      Znyc.Cloudcar.Admin.Commons/Core/DbContextCore/PostgreSQLDbContext.cs
  61. 62
      Znyc.Cloudcar.Admin.Commons/Core/DbContextCore/SQLiteDbContext.cs
  62. 225
      Znyc.Cloudcar.Admin.Commons/Core/DbContextCore/SqlServerDbContext.cs
  63. 16
      Znyc.Cloudcar.Admin.Commons/Core/Dtos/DeletesInputDto.cs
  64. 14
      Znyc.Cloudcar.Admin.Commons/Core/Dtos/IInputDto.cs
  65. 9
      Znyc.Cloudcar.Admin.Commons/Core/Dtos/IOutputDto.cs
  66. 80
      Znyc.Cloudcar.Admin.Commons/Core/Dtos/InputDtoValidateExtensions.cs
  67. 39
      Znyc.Cloudcar.Admin.Commons/Core/Dtos/SearchInputDto.cs
  68. 491
      Znyc.Cloudcar.Admin.Commons/Core/IDbContext/IDbContextCore.cs
  69. 24
      Znyc.Cloudcar.Admin.Commons/Core/IDbContext/IDbContextFactory.cs
  70. 6
      Znyc.Cloudcar.Admin.Commons/Core/IDbContext/IMySqlDbContext.cs
  71. 6
      Znyc.Cloudcar.Admin.Commons/Core/IDbContext/IOracleDbContext.cs
  72. 6
      Znyc.Cloudcar.Admin.Commons/Core/IDbContext/IPostgreSQLDbContext.cs
  73. 6
      Znyc.Cloudcar.Admin.Commons/Core/IDbContext/ISQLiteDbContext.cs
  74. 6
      Znyc.Cloudcar.Admin.Commons/Core/IDbContext/ISqlServerDbContext.cs
  75. 14
      Znyc.Cloudcar.Admin.Commons/Core/IRepositories/IReadOnlyRepository.cs
  76. 833
      Znyc.Cloudcar.Admin.Commons/Core/IRepositories/IRepository.cs
  77. 629
      Znyc.Cloudcar.Admin.Commons/Core/IServices/IService.cs
  78. 55
      Znyc.Cloudcar.Admin.Commons/Core/Models/BaseEntity.cs
  79. 12
      Znyc.Cloudcar.Admin.Commons/Core/Models/BaseViewModel.cs
  80. 9
      Znyc.Cloudcar.Admin.Commons/Core/Models/Entity.cs
  81. 14
      Znyc.Cloudcar.Admin.Commons/Core/Models/IBaseEntity.cs
  82. 20
      Znyc.Cloudcar.Admin.Commons/Core/Models/ICreationAudited.cs
  83. 18
      Znyc.Cloudcar.Admin.Commons/Core/Models/IDataAuthEnabled.cs
  84. 13
      Znyc.Cloudcar.Admin.Commons/Core/Models/IDeleteAudited.cs
  85. 9
      Znyc.Cloudcar.Admin.Commons/Core/Models/IEntity.cs
  86. 10
      Znyc.Cloudcar.Admin.Commons/Core/Models/IEntityHash.cs
  87. 20
      Znyc.Cloudcar.Admin.Commons/Core/Models/IExpirable.cs
  88. 20
      Znyc.Cloudcar.Admin.Commons/Core/Models/IModificationAudited.cs
  89. 13
      Znyc.Cloudcar.Admin.Commons/Core/Models/IMustHaveTenant.cs
  90. 22
      Znyc.Cloudcar.Admin.Commons/Core/Module/AutoMapperService.cs
  91. 88
      Znyc.Cloudcar.Admin.Commons/Core/Module/MoudleService.cs
  92. 2255
      Znyc.Cloudcar.Admin.Commons/Core/Repositories/BaseRepository.cs
  93. 1006
      Znyc.Cloudcar.Admin.Commons/Core/Services/BaseService.cs
  94. 22
      Znyc.Cloudcar.Admin.Commons/Cos/CosOptions.cs
  95. 251
      Znyc.Cloudcar.Admin.Commons/Data/Check.cs
  96. 95
      Znyc.Cloudcar.Admin.Commons/Data/MicroDataTable.cs
  97. 52
      Znyc.Cloudcar.Admin.Commons/Data/MicroDataTableHelper.cs
  98. 9
      Znyc.Cloudcar.Admin.Commons/DependencyInjection/IPrivateDependency.cs
  99. 9
      Znyc.Cloudcar.Admin.Commons/DependencyInjection/IScopedDependency.cs
  100. 9
      Znyc.Cloudcar.Admin.Commons/DependencyInjection/ISingletonDependency.cs

25
.dockerignore

@ -0,0 +1,25 @@
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/azds.yaml
**/bin
**/charts
**/docker-compose*
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md

63
.gitattributes

@ -0,0 +1,63 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain

316
.gitignore

@ -0,0 +1,316 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
bin/
obj/
logs/
upload/
*.[pdb]
**/bin/**
**/obj/**
.vs/*
**/wwwroot/Generatecode/**
**/wwwroot/upload/**
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]ogs/
app_data/
[Aa]pps/
[Bb]in/
[Oo]bj/
app_data/
[Aa]pps/
**/[Bb]in/**
**/[Oo]bj/**
**.cache
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
**/Properties/launchSettings.json
**.cache
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# DNX
project.lock.json
project.fragment.lock.json
artifacts/
# vue
.DS_Store
node_modules/
dist/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
package-lock.json
tests/**/coverage/
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
#*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignoreable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
*.dll
/Yuebon.Api/Yuebon.WebApi/wwwroot/upload
/Yuebon.Api/Yuebon.WebApi/upload/opp/20190912
/Yuebon.Manager/Yuebon.WebApp/wwwroot/upload/cqinwn/opp/2019/11/18/2019111816150498189370_300x300.jpeg
/Yuebon.Manager/Yuebon.WebApp/wwwroot/upload/cqinwn/opp/2019/11/18/2019111816150498189370.jpeg
/Yuebon.Manager/Yuebon.WebApp/wwwroot/upload/cqinwn/opp/2019/11/18/2019111816130781914822_300x300.jpeg
/Yuebon.Manager/Yuebon.WebApp/wwwroot/upload/cqinwn/opp/2019/11/18/2019111816130781914822.jpeg
/Yuebon.Manager/Yuebon.WebApp/wwwroot/upload/cqinwn/opp/2019/11/18/2019111816104345142749_300x300.jpg
/Yuebon.Manager/Yuebon.WebApp/wwwroot/upload/cqinwn/opp/2019/11/18/2019111816104345142749.jpg
/Yuebon.Manager/Yuebon.WebApp/wwwroot/upload/cqinwn/opp/2019/11/18/2019111816092171662104_300x300.jpg
/Yuebon.Manager/Yuebon.WebApp/wwwroot/upload/cqinwn/opp/2019/11/18/2019111816092171662104.jpg
/Yuebon.NetCore/Yuebon.Commons/Core/DataManager/DbAppSettings.cs

30
Dockerfile

@ -0,0 +1,30 @@
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 8091
EXPOSE 443
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["Znyc.Cloudcar.Admin.WebApi/Znyc.Cloudcar.Admin.WebApi.csproj", "Znyc.Cloudcar.Admin.WebApi/"]
COPY ["Znyc.Cloudcar.Admin.Security.Core/Znyc.Cloudcar.Admin.Security.Core.csproj", "Znyc.Cloudcar.Admin.Security.Core/"]
COPY ["Znyc.Cloudcar.Admin.Commons/Znyc.Cloudcar.Admin.Commons.csproj", "Znyc.Cloudcar.Admin.Commons/"]
COPY ["Znyc.Cloudcar.Admin.WeChat.Core/Znyc.Cloudcar.Admin.WeChat.Core.csproj", "Znyc.Cloudcar.Admin.WeChat.Core/"]
COPY ["Znyc.Cloudcar.Admin.MongoDb/Znyc.Cloudcar.Admin.MongoDb.Core.csproj", "Znyc.Cloudcar.Admin.MongoDb/"]
COPY ["Znyc.Cloudcar.Admin.AspNetCore/Znyc.Cloudcar.Admin.AspNetCore.csproj", "Znyc.Cloudcar.Admin.AspNetCore/"]
RUN dotnet restore "Znyc.Cloudcar.Admin.WebApi/Znyc.Cloudcar.Admin.WebApi.csproj"
COPY . .
WORKDIR "/src/Znyc.Cloudcar.Admin.WebApi"
RUN dotnet build "Znyc.Cloudcar.Admin.WebApi.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "Znyc.Cloudcar.Admin.WebApi.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Znyc.Cloudcar.Admin.WebApi.dll"]

21
LICENSE

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 znyc_recruitment
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

804
Znyc.Cloudcar.Admin.AspNetCore/AspNetCore.xml

@ -0,0 +1,804 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>Znyc.Cloudcar.Admin.AspNetCore</name>
</assembly>
<members>
<member name="T:Znyc.Cloudcar.Admin.AspNetCore.Entitys.ErrCode">
<summary>
错误代码描述
</summary>
</member>
<member name="F:Znyc.Cloudcar.Admin.AspNetCore.Entitys.ErrCode.err0">
<summary>
请求成功
</summary>
</member>
<member name="F:Znyc.Cloudcar.Admin.AspNetCore.Entitys.ErrCode.successCode">
<summary>
请求成功代码0
</summary>
</member>
<member name="F:Znyc.Cloudcar.Admin.AspNetCore.Entitys.ErrCode.err1">
<summary>
请求失败
</summary>
</member>
<member name="F:Znyc.Cloudcar.Admin.AspNetCore.Entitys.ErrCode.failCode">
<summary>
请求失败代码1
</summary>
</member>
<member name="F:Znyc.Cloudcar.Admin.AspNetCore.Entitys.ErrCode.err40001">
<summary>
获取access_token时AppID或AppSecret错误。请开发者认真比对appid和AppSecret的正确性,或查看是否正在为恰当的应用调用接口
</summary>
</member>
<member name="F:Znyc.Cloudcar.Admin.AspNetCore.Entitys.ErrCode.err40002">
<summary>
调用接口的服务器URL地址不正确,请联系供应商进行设置
</summary>
</member>
<member name="F:Znyc.Cloudcar.Admin.AspNetCore.Entitys.ErrCode.err40003">
<summary>
请确保grant_type字段值为client_credential
</summary>
</member>
<member name="F:Znyc.Cloudcar.Admin.AspNetCore.Entitys.ErrCode.err40004">
<summary>
不合法的凭证类型
</summary>
</member>
<member name="F:Znyc.Cloudcar.Admin.AspNetCore.Entitys.ErrCode.err40005">
<summary>
用户令牌accesstoken超时失效
</summary>
</member>
<member name="F:Znyc.Cloudcar.Admin.AspNetCore.Entitys.ErrCode.err40006">
<summary>
您未被授权使用该功能,请重新登录试试或联系管理员进行处理
</summary>
</member>
<member name="F:Znyc.Cloudcar.Admin.AspNetCore.Entitys.ErrCode.err40007">
<summary>
传递参数出现错误
</summary>
</member>
<member name="F:Znyc.Cloudcar.Admin.AspNetCore.Entitys.ErrCode.err43001">
<summary>
更新数据失败
</summary>
</member>
<member name="F:Znyc.Cloudcar.Admin.AspNetCore.Entitys.ErrCode.err43002">
<summary>
更新数据失败
</summary>
</member>
<member name="F:Znyc.Cloudcar.Admin.AspNetCore.Entitys.ErrCode.err43003">
<summary>
物理删除数据失败
</summary>
</member>
<member name="F:Znyc.Cloudcar.Admin.AspNetCore.Entitys.ErrCode.err50001">
<summary>
该用户不存在
</summary>
</member>
<member name="F:Znyc.Cloudcar.Admin.AspNetCore.Entitys.ErrCode.err50002">
<summary>
该用户已存在
</summary>
</member>
<member name="F:Znyc.Cloudcar.Admin.AspNetCore.Entitys.ErrCode.err50003">
<summary>
会员注册失败
</summary>
</member>
<member name="F:Znyc.Cloudcar.Admin.AspNetCore.Entitys.ErrCode.err60001">
<summary>
查询数据不存在
</summary>
</member>
<member name="T:Znyc.Cloudcar.Admin.AspNetCore.Common.MyApiException">
<summary>
自定义异常信息
</summary>
</member>
<member name="P:Znyc.Cloudcar.Admin.AspNetCore.Common.MyApiException.Msg">
<summary>
异常消息
</summary>
</member>
<member name="P:Znyc.Cloudcar.Admin.AspNetCore.Common.MyApiException.Success">
<summary>
成功状态
</summary>
</member>
<member name="P:Znyc.Cloudcar.Admin.AspNetCore.Common.MyApiException.ErrCode">
<summary>
提示代码
</summary>
</member>
<member name="M:Znyc.Cloudcar.Admin.AspNetCore.Common.MyApiException.#ctor(System.String)">
<summary>
异常
</summary>
<param name="message"></param>
</member>
<member name="M:Znyc.Cloudcar.Admin.AspNetCore.Common.MyApiException.#ctor(System.String,System.String)">
<summary>
</summary>
<param name="message"></param>
<param name="errcode"></param>
</member>
<member
name="M:Znyc.Cloudcar.Admin.AspNetCore.Common.MyApiException.#ctor(System.String,System.Boolean,System.String)">
<summary>
</summary>
<param name="message"></param>
<param name="success"></param>
<param name="errcode"></param>
</member>
<member name="T:Znyc.Cloudcar.Admin.AspNetCore.Controllers.CheckController">
<summary>
sso验证
<para>其他站点通过后台Post来认证</para>
<para>或使用静态类Znyc.Cloudcar.Admin.Security.Application.SSO.AuthHelper访问</para>
</summary>
</member>
<member
name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.CheckController.GetStatus(System.String,System.String)">
<summary>
检验token是否有效
</summary>
<param name="token">The token.</param>
<param name="requestid">请求Id备用参数.</param>
</member>
<member name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.CheckController.GetUser(System.String,System.String)">
<summary>
根据token获取用户及用户可访问的所有资源
</summary>
<param name="token"></param>
<param name="requestid">备用参数.</param>
</member>
<member
name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.CheckController.GetUserName(System.String,System.String)">
<summary>
根据token获取用户名称
</summary>
<param name="token"></param>
<param name="requestid">备用参数.</param>
</member>
<member
name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.CheckController.Login(Znyc.Cloudcar.Admin.AspNetCore.SSO.PassportLoginRequest)">
<summary>
登录接口
</summary>
<param name="request">登录参数</param>
<returns></returns>
</member>
<member name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.CheckController.Logout(System.String,System.String)">
<summary>
注销登录
</summary>
<param name="token"></param>
<param name="requestid">备用参数.</param>
</member>
<member name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.CheckController.GetToken">
<summary>
获取token
</summary>
<returns></returns>
</member>
<member name="T:Znyc.Cloudcar.Admin.AspNetCore.Controllers.FilesController">
<summary>
文件上传
</summary>
</member>
<member
name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.FilesController.#ctor(Znyc.Cloudcar.Admin.Security.Application.UploadFileApp,Microsoft.AspNetCore.Hosting.IWebHostEnvironment)">
<summary>
</summary>
<param name="app"></param>
</member>
<member
name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.FilesController.Upload(Microsoft.AspNetCore.Http.IFormCollection)">
<summary>
单文件上传接口
</summary>
<param name="files"></param>
<returns>服务器存储的文件信息</returns>
</member>
<member
name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.FilesController.Uploads(Microsoft.AspNetCore.Http.IFormCollection)">
<summary>
批量上传文件接口
</summary>
<param name="files"></param>
<returns>服务器存储的文件信息</returns>
</member>
<member
name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.FilesController.Adds(Microsoft.AspNetCore.Http.IFormFileCollection,System.String,System.String)">
<summary>
批量上传文件
</summary>
<param name="files">文件</param>
<param name="belongApp">所属应用,如文章article</param>
<param name="belongAppId">所属应用ID,如文章id</param>
<returns></returns>
</member>
<member
name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.FilesController.Add(Microsoft.AspNetCore.Http.IFormFile,System.String,System.String)">
<summary>
单个上传文件
</summary>
<param name="file"></param>
<returns></returns>
</member>
<member
name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.FilesController.UploadFile(System.String,System.Byte[])">
<summary>
实现文件上传到服务器保存,并生成缩略图
</summary>
<param name="fileName">文件名称</param>
<param name="fileBuffers">文件字节流</param>
</member>
<member name="T:Znyc.Cloudcar.Admin.AspNetCore.Controllers.IdentityController">
<summary>
Identity控制器
</summary>
</member>
<member name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.IdentityController.Get">
<summary>
</summary>
<returns></returns>
</member>
<member name="T:Znyc.Cloudcar.Admin.AspNetCore.Controllers.LoginController">
<summary>
用户登录接口控制器
</summary>
</member>
<member
name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.LoginController.#ctor(Znyc.Cloudcar.Admin.Security.IServices.IUserService)">
<summary>
构造函数注入服务
</summary>
<param name="service"></param>
</member>
<member
name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.LoginController.GetCheckUser(System.String,System.String,System.String)">
<summary>
登录验证用户
</summary>
<param name="username">用户名</param>
<param name="password">密码</param>
<param name="url">返回Url</param>
<returns>返回用户User对象</returns>
</member>
<member name="T:Znyc.Cloudcar.Admin.AspNetCore.Controllers.TokenController">
<summary>
Token令牌接口控制器
</summary>
</member>
<member
name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.TokenController.#ctor(Znyc.Cloudcar.Admin.Security.IServices.IAPPService,Znyc.Cloudcar.Admin.Commons.Options.JwtOption)">
<summary>
</summary>
<param name="_iAPPService"></param>
<param name="jwtModel"></param>
</member>
<member
name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.TokenController.Get(System.String,System.String,System.String)">
<summary>
根据应用信息获得token令牌
</summary>
<param name="grant_type">获取access_token填写client_credential</param>
<param name="appid">用户唯一凭证,应用AppId</param>
<param name="secret">应用密钥AppSecret</param>
<returns></returns>
</member>
<member name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.TokenController.CheckToken(System.String)">
<summary>
验证token的合法性。
</summary>
<param name="token"></param>
<returns></returns>
</member>
<member name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.TokenController.RefreshToken(System.String)">
<summary>
刷新token。
</summary>
<param name="token"></param>
<returns></returns>
</member>
<member name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.TokenController.ToJsonContent(System.Object)">
<summary>
把object对象转换为ContentResult
</summary>
<param name="obj"></param>
<returns></returns>
</member>
<member name="T:Znyc.Cloudcar.Admin.AspNetCore.Controllers.ApiController">
<summary>
WebApi控制器基类
</summary>
</member>
<member name="F:Znyc.Cloudcar.Admin.AspNetCore.Controllers.ApiController.AdminCurrentUser">
<summary>
当前登录的用户属性
</summary>
</member>
<member name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.ApiController.ToJsonContent(System.Object)">
<summary>
把object对象转换为ContentResult
</summary>
<param name="obj"></param>
<returns></returns>
</member>
<member name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.ApiController.CheckToken(System.String)">
<summary>
验证token的合法性。如果不合法,返回MyApiException异常
</summary>
<returns></returns>
</member>
<member name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.ApiController.GetToken">
<summary>
获取token
</summary>
<returns></returns>
</member>
<member name="T:Znyc.Cloudcar.Admin.AspNetCore.Controllers.AreaApiController`2">
<summary>
基本控制器,增删改查
</summary>
<typeparam name="T">实体类型</typeparam>
<typeparam name="TServicen">Service类型</typeparam>
</member>
<member name="F:Znyc.Cloudcar.Admin.AspNetCore.Controllers.AreaApiController`2._service">
<summary>
服务接口
</summary>
</member>
<member name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.AreaApiController`2.#ctor(`1)">
<summary>
构造方法
</summary>
<param name="_service"></param>
</member>
<member name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.AreaApiController`2.OnBeforeInsert(`0)">
<summary>
在插入数据前对数据的修改操作
</summary>
<param name="info"></param>
<returns></returns>
</member>
<member name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.AreaApiController`2.OnBeforeUpdate(`0)">
<summary>
在更新数据前对数据的修改操作
</summary>
<param name="info"></param>
<returns></returns>
</member>
<member name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.AreaApiController`2.OnBeforeSoftDelete(`0)">
<summary>
在软删除数据前对数据的修改操作
</summary>
<param name="info"></param>
<returns></returns>
</member>
<member name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.AreaApiController`2.InsertAsync(`0)">
<summary>
异步新增数据
</summary>
<param name="info"></param>
<returns></returns>
</member>
<member name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.AreaApiController`2.UpdateAsync(`0,System.String)">
<summary>
异步更新数据
</summary>
<param name="info"></param>
<param name="id">主键Id</param>
<returns></returns>
</member>
<member name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.AreaApiController`2.Delete(System.String)">
<summary>
物理删除
</summary>
<param name="id">主键Id</param>
</member>
<member name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.AreaApiController`2.DeleteAsync(System.String)">
<summary>
异步物理删除
</summary>
<param name="id">主键Id</param>
</member>
<member
name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.AreaApiController`2.DeleteSoft(System.String,System.String)">
<summary>
软删除信息
</summary>
<param name="id">主键Id</param>
<param name="bltag">删除标识,默认为1:即设为删除,0:未删除</param>
</member>
<member
name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.AreaApiController`2.DeleteSoftAsync(System.String,System.String)">
<summary>
异步软删除信息
</summary>
<param name="id">主键Id</param>
<param name="bltag">删除标识,默认为1:即设为删除,0:未删除</param>
</member>
<member
name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.AreaApiController`2.SetEnabledMark(System.String,System.String)">
<summary>
设为数据有效性
</summary>
<param name="id">主键Id</param>
<param name="bltag">有效标识,默认为1:即设为无效,0:有效</param>
</member>
<member
name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.AreaApiController`2.SetEnabledMarkAsync(System.String,System.String)">
<summary>
异步设为数据有效性
</summary>
<param name="id">主键Id</param>
<param name="bltag">有效标识,默认为1:即设为无效,0:有效</param>
</member>
<member name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.AreaApiController`2.GetById(System.String)">
<summary>
根据主键Id获取一个对象信息
</summary>
<param name="id">主键Id</param>
<returns></returns>
</member>
<member name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.AreaApiController`2.FindWithPager(`0)">
<summary>
根据条件查询数据库,并返回对象集合(用于分页数据显示)
</summary>
<param name="info">info</param>
<returns>指定对象的集合</returns>
</member>
<member name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.AreaApiController`2.GetPagerInfo">
<summary>
根据Request参数获取分页对象数据
</summary>
<returns></returns>
</member>
<member
name="M:Znyc.Cloudcar.Admin.AspNetCore.Controllers.AreaApiController`2.GetPagerCondition(System.Boolean)">
<summary>
获取分页操作的查询条件
</summary>
<returns></returns>
</member>
<member name="T:Znyc.Cloudcar.Admin.AspNetCore.Mvc.Filter.ExceptionHandlingAttribute">
<summary>
表示一个特性,该特性用于全局捕获程序运行异常信息。
</summary>
</member>
<member
name="M:Znyc.Cloudcar.Admin.AspNetCore.Mvc.Filter.ExceptionHandlingAttribute.OnException(Microsoft.AspNetCore.Mvc.Filters.ExceptionContext)">
<summary>
</summary>
<param name="context"></param>
</member>
<member name="T:Znyc.Cloudcar.Admin.AspNetCore.Mvc.Filter.RemoveVersionFromParameter">
<summary>
</summary>
</member>
<member
name="M:Znyc.Cloudcar.Admin.AspNetCore.Mvc.Filter.RemoveVersionFromParameter.Apply(Microsoft.OpenApi.Entitys.OpenApiOperation,Swashbuckle.AspNetCore.SwaggerGen.OperationFilterContext)">
<summary>
</summary>
<param name="operation"></param>
<param name="context"></param>
</member>
<member name="T:Znyc.Cloudcar.Admin.AspNetCore.Mvc.Filter.SwaggerFileUploadFilter">
<summary>
Swagger 上传文件过滤器
</summary>
</member>
<member
name="M:Znyc.Cloudcar.Admin.AspNetCore.Mvc.Filter.SwaggerFileUploadFilter.Apply(Microsoft.OpenApi.Entitys.OpenApiOperation,Swashbuckle.AspNetCore.SwaggerGen.OperationFilterContext)">
<summary>
应用过滤器
</summary>
<param name="operation"></param>
<param name="context"></param>
</member>
<member name="T:Znyc.Cloudcar.Admin.AspNetCore.Mvc.HiddenApiAttribute">
<summary>
隐藏接口,不生成到swagger文档展示
</summary>
</member>
<member name="T:Znyc.Cloudcar.Admin.AspNetCore.Mvc.HiddenApiFilter">
<summary>
隐藏接口,不生成到swagger文档展示
</summary>
</member>
<member
name="M:Znyc.Cloudcar.Admin.AspNetCore.Mvc.HiddenApiFilter.Apply(Microsoft.OpenApi.Entitys.OpenApiDocument,Swashbuckle.AspNetCore.SwaggerGen.DocumentFilterContext)">
<summary>
实现Apply方法
</summary>
<param name="swaggerDoc"></param>
<param name="documentFilterContext"></param>
</member>
<member name="T:Znyc.Cloudcar.Admin.AspNetCore.Mvc.FunctionAuthorizationFilter">
<summary>
功能权限授权验证
</summary>
</member>
<member
name="M:Znyc.Cloudcar.Admin.AspNetCore.Mvc.FunctionAuthorizationFilter.OnAuthorization(Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext)">
<summary>
</summary>
<param name="context"></param>
</member>
<member name="T:Znyc.Cloudcar.Admin.AspNetCore.Mvc.FunctionAuthorizeAttribute">
<summary>
</summary>
</member>
<member name="P:Znyc.Cloudcar.Admin.AspNetCore.Mvc.FunctionAuthorizeAttribute.Permission">
<summary>
权限
</summary>
</member>
<member name="M:Znyc.Cloudcar.Admin.AspNetCore.Mvc.FunctionAuthorizeAttribute.#ctor(System.String)">
<summary>
构造函数
</summary>
<param name="permission"></param>
</member>
<member name="T:Znyc.Cloudcar.Admin.AspNetCore.Mvc.TokenProvider">
<summary>
Token令牌提供类
</summary>
</member>
<member name="M:Znyc.Cloudcar.Admin.AspNetCore.Mvc.TokenProvider.#ctor">
<summary>
构造函数
</summary>
</member>
<member
name="M:Znyc.Cloudcar.Admin.AspNetCore.Mvc.TokenProvider.#ctor(Znyc.Cloudcar.Admin.Commons.Options.JwtOption)">
<summary>
构造函数,初花jwtmodel
</summary>
<param name="jwtModel"></param>
</member>
<member
name="M:Znyc.Cloudcar.Admin.AspNetCore.Mvc.TokenProvider.GenerateToken(System.String,System.String,System.String)">
<summary>
直接通过appid和加密字符串获取访问令牌接口
</summary>
<param name="grant_type">获取access_token填写client_credential</param>
<param name="appid">用户唯一凭证</param>
<param name="secret">用户唯一凭证密钥,即appsecret</param>
<returns></returns>
</member>
<member name="M:Znyc.Cloudcar.Admin.AspNetCore.Mvc.TokenProvider.ValidateToken(System.String)">
<summary>
检查用户的Token有效性
</summary>
<param name="token">token令牌</param>
<returns></returns>
</member>
<member
name="M:Znyc.Cloudcar.Admin.AspNetCore.Mvc.TokenProvider.LoginToken(Znyc.Cloudcar.Admin.Security.Entitys.User,System.String)">
<summary>
根据用户获取token
</summary>
<param name="userLogOn"></param>
<returns></returns>
</member>
<member name="M:Znyc.Cloudcar.Admin.AspNetCore.SSO.AuthHelper.GetToken">
<summary>
根据URL中的Token参数或Cookie获取token
</summary>
<returns></returns>
</member>
<member name="M:Znyc.Cloudcar.Admin.AspNetCore.SSO.AuthHelper.CheckLogin(System.String,System.String)">
<summary>
检查用户登录状态
</summary>
<param name="token">token</param>
<param name="remark">备注信息</param>
<returns></returns>
</member>
<member name="M:Znyc.Cloudcar.Admin.AspNetCore.SSO.AuthHelper.CheckLogin(System.String)">
<summary>
检查用户登录状态
<para>通过URL中的Token参数或Cookie中的Token</para>
</summary>
<param name="remark">备注信息</param>
</member>
<member name="M:Znyc.Cloudcar.Admin.AspNetCore.SSO.AuthHelper.GetAdminCurrentUser(System.String)">
<summary>
获取当前登录的用户信息
<para>通过URL中的Token参数或Cookie中的Token</para>
</summary>
<param name="remark">The remark.</param>
<returns>LoginUserVM.</returns>
</member>
<member name="M:Znyc.Cloudcar.Admin.AspNetCore.SSO.AuthHelper.GetUserName(System.String)">
<summary>
获取当前登录的用户名
<para>通过URL中的Token参数或Cookie中的Token</para>
</summary>
<param name="remark">The remark.</param>
<returns>System.String.</returns>
</member>
<member
name="M:Znyc.Cloudcar.Admin.AspNetCore.SSO.AuthHelper.Login(System.String,System.String,System.String,System.String)">
<summary>
登录接口
</summary>
<param name="appKey">应用程序key.</param>
<param name="appSecret">应用程序Secret.</param>
<param name="username">用户名</param>
<param name="pwd">密码</param>
<returns>System.String.</returns>
</member>
<member name="M:Znyc.Cloudcar.Admin.AspNetCore.SSO.AuthHelper.Logout">
<summary>
注销
</summary>
</member>
<member name="T:Znyc.Cloudcar.Admin.AspNetCore.SSO.LoginResult">
<summary>
登录返回结果
</summary>
</member>
<member name="F:Znyc.Cloudcar.Admin.AspNetCore.SSO.LoginResult.ReturnUrl">
<summary>
跳转Url
</summary>
</member>
<member name="F:Znyc.Cloudcar.Admin.AspNetCore.SSO.LoginResult.AccessToken">
<summary>
token
</summary>
</member>
<member name="T:Znyc.Cloudcar.Admin.AspNetCore.SSO.PassportLoginRequest">
<summary>
系统登录请求实体
</summary>
</member>
<member name="P:Znyc.Cloudcar.Admin.AspNetCore.SSO.PassportLoginRequest.Account">
<summary>
账号
</summary>
</member>
<member name="P:Znyc.Cloudcar.Admin.AspNetCore.SSO.PassportLoginRequest.Password">
<summary>
密码
</summary>
</member>
<member name="P:Znyc.Cloudcar.Admin.AspNetCore.SSO.PassportLoginRequest.SystemCode">
<summary>
系统编码
</summary>
</member>
<member
name="M:Znyc.Cloudcar.Admin.AspNetCore.SSO.SSOAuthHelper.Validate(Znyc.Cloudcar.Admin.AspNetCore.SSO.PassportLoginRequest)">
<summary>
用户登录验证,主要用管理后台、H5和App应用用户登录
</summary>
<param name="model"></param>
<returns></returns>
</member>
<member name="P:Znyc.Cloudcar.Admin.AspNetCore.SSO.TokenModel.Access_Token">
<summary>
获取到的凭证值
</summary>
</member>
<member name="P:Znyc.Cloudcar.Admin.AspNetCore.SSO.TokenModel.Expires_In">
<summary>
获取到的凭证值
</summary>
</member>
<member name="P:Znyc.Cloudcar.Admin.AspNetCore.SSO.AdminCurrentUser.UserId">
<summary>
用户ID
</summary>
</member>
<member name="P:Znyc.Cloudcar.Admin.AspNetCore.SSO.AdminCurrentUser.Account">
<summary>
用户账号
</summary>
</member>
<member name="P:Znyc.Cloudcar.Admin.AspNetCore.SSO.AdminCurrentUser.Name">
<summary>
用户名
</summary>
</member>
<member name="P:Znyc.Cloudcar.Admin.AspNetCore.SSO.AdminCurrentUser.UserName">
<summary>
昵称
</summary>
</member>
<member name="P:Znyc.Cloudcar.Admin.AspNetCore.SSO.AdminCurrentUser.HeadIcon">
<summary>
头像
</summary>
</member>
<member name="P:Znyc.Cloudcar.Admin.AspNetCore.SSO.AdminCurrentUser.Gender">
<summary>
性别
</summary>
</member>
<member name="P:Znyc.Cloudcar.Admin.AspNetCore.SSO.AdminCurrentUser.MemberGradeId">
<summary>
头像
</summary>
</member>
<member name="P:Znyc.Cloudcar.Admin.AspNetCore.SSO.AdminCurrentUser.ReferralUserId">
<summary>
上级推广员
</summary>
</member>
<member name="P:Znyc.Cloudcar.Admin.AspNetCore.SSO.AdminCurrentUser.CreateTime">
<summary>
注册时间
</summary>
</member>
<member name="P:Znyc.Cloudcar.Admin.AspNetCore.SSO.AdminCurrentUser.Role">
<summary>
角色编码,多个角色,使用“,”分格
</summary>
</member>
<member name="P:Znyc.Cloudcar.Admin.AspNetCore.SSO.AdminCurrentUser.OtherOpenObj">
<summary>
其他对象
</summary>
</member>
<member name="T:Znyc.Cloudcar.Admin.AspNetCore.UI.SearchModel">
<summary>
查询条件公共实体类
</summary>
</member>
<member name="P:Znyc.Cloudcar.Admin.AspNetCore.UI.SearchModel.Keywords">
<summary>
关键词
</summary>
</member>
<member name="P:Znyc.Cloudcar.Admin.AspNetCore.UI.SearchModel.Order">
<summary>
排序方式 默认asc
</summary>
</member>
<member name="P:Znyc.Cloudcar.Admin.AspNetCore.UI.SearchModel.Sort">
<summary>
排序字段 默认Id
</summary>
</member>
<member name="P:Znyc.Cloudcar.Admin.AspNetCore.UI.SearchModel.PageNo">
<summary>
第几页
</summary>
</member>
<member name="P:Znyc.Cloudcar.Admin.AspNetCore.UI.SearchModel.PageSize">
<summary>
每页显示数量
</summary>
</member>
<member name="T:Znyc.Cloudcar.Admin.WebApi.Common.SessionObject">
<summary>
SessionObject是登录之后,给客户端传回的对象
</summary>
</member>
<member name="P:Znyc.Cloudcar.Admin.WebApi.Common.SessionObject.SessionKey">
<summary>
SessionKey
</summary>
</member>
<member name="P:Znyc.Cloudcar.Admin.WebApi.Common.SessionObject.LogonUser">
<summary>
当前登录的用户的信息
</summary>
</member>
</members>
</doc>

49
Znyc.Cloudcar.Admin.AspNetCore/Common/CorsMiddleware.cs

@ -0,0 +1,49 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using System.Threading.Tasks;
namespace Znyc.Cloudcar.Admin.AspNetCore.Common
{
/// <summary>
/// 跨域中间件
/// 解决net core 3.1 跨域 Cors 找不到 “Access-Control-Allow-Origin”
/// </summary>
public class CorsMiddleware
{
/// <summary>
/// </summary>
private readonly RequestDelegate _next;
/// <summary>
/// </summary>
/// <param name="next"></param>
public CorsMiddleware(RequestDelegate next)
{
_next = next;
}
/// <summary>
/// </summary>
/// <param name="httpContext"></param>
/// <returns></returns>
public async Task Invoke(HttpContext httpContext)
{
if (!httpContext.Response.Headers.ContainsKey("Access-Control-Allow-Origin"))
{
httpContext.Response.Headers.Add("Access-Control-Allow-Origin", "*");
}
await _next(httpContext);
}
}
/// <summary>
/// </summary>
public static class CorsMiddlewareExtensions
{
public static IApplicationBuilder UseCorsMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<CorsMiddleware>();
}
}
}

115
Znyc.Cloudcar.Admin.AspNetCore/Common/ErrCode.cs

@ -0,0 +1,115 @@
namespace Znyc.Cloudcar.Admin.AspNetCore.Entitys
{
/// <summary>
/// 错误代码描述
/// </summary>
public static class ErrCode
{
/// <summary>
/// 请求成功
/// </summary>
public static string err0 = "请求成功";
/// <summary>
/// 请求成功代码0
/// </summary>
public static string successCode = "0";
/// <summary>
/// 请求失败
/// </summary>
public static string err1 = "请求失败";
/// <summary>
/// 请求失败代码1
/// </summary>
public static string failCode = "1";
/// <summary>
/// 获取access_token时AppID或AppSecret错误。请开发者认真比对appid和AppSecret的正确性,或查看是否正在为恰当的应用调用接口
/// </summary>
public static string err40001 =
"获取access_token时AppID或AppSecret错误。请开发者认真比对appid和AppSecret的正确性,或查看是否正在为恰当的应用调用接口";
/// <summary>
/// 调用接口的服务器URL地址不正确,请联系供应商进行设置
/// </summary>
public static string err40002 = "调用接口的服务器URL地址不正确,请联系供应商进行授权";
/// <summary>
/// 请确保grant_type字段值为client_credential
/// </summary>
public static string err40003 = "请确保grant_type字段值为client_credential";
/// <summary>
/// 不合法的凭证类型
/// </summary>
public static string err40004 = "不合法的凭证类型";
/// <summary>
/// 用户令牌accesstoken超时失效
/// </summary>
public static string err40005 = "用户令牌accesstoken超时失效";
/// <summary>
/// 您未被授权使用该功能,请重新登录试试或联系管理员进行处理
/// </summary>
public static string err40006 = "您未被授权使用该功能,请重新登录试试或联系系统管理员进行处理";
/// <summary>
/// 传递参数出现错误
/// </summary>
public static string err40007 = "传递参数出现错误";
/// <summary>
/// 用户未登录或超时
/// </summary>
public static string err40008 = "用户未登录或超时";
/// <summary>
/// 程序异常
/// </summary>
public static string err40110 = "程序异常";
/// <summary>
/// 新增数据失败
/// </summary>
public static string err43001 = "新增数据失败";
/// <summary>
/// 更新数据失败
/// </summary>
public static string err43002 = "更新数据失败";
/// <summary>
/// 物理删除数据失败
/// </summary>
public static string err43003 = "删除数据失败";
/// <summary>
/// 该用户不存在
/// </summary>
public static string err50001 = "该数据不存在";
/// <summary>
/// 该用户已存在
/// </summary>
public static string err50002 = "用户已存在,请登录或重新注册!";
/// <summary>
/// 会员注册失败
/// </summary>
public static string err50003 = "会员注册失败";
/// <summary>
/// 查询数据不存在
/// </summary>
public static string err60001 = "查询数据不存在";
}
}

25
Znyc.Cloudcar.Admin.AspNetCore/Common/Initialization.cs

@ -0,0 +1,25 @@
using Znyc.Cloudcar.Admin.Commons.Cache;
using Znyc.Cloudcar.Admin.Commons.Helpers;
using Znyc.Cloudcar.Admin.Security.Entitys;
namespace Znyc.Cloudcar.Admin.AspNetCore.Common
{
/// <summary>
/// 系统初始化内容
/// </summary>
public abstract class Initialization
{
/// <summary>
/// 初始化
/// </summary>
public virtual void Initial()
{
CacheHelper cacheHelper = new CacheHelper();
SysSettingEntity sysSetting = XmlConverter.Deserialize<SysSettingEntity>("xmlconfig/sys.config");
if (sysSetting != null)
{
cacheHelper.Add("SysSetting", sysSetting);
}
}
}
}

93
Znyc.Cloudcar.Admin.AspNetCore/Common/MyApiException.cs

@ -0,0 +1,93 @@
using System;
using System.Runtime.Serialization;
namespace Znyc.Cloudcar.Admin.AspNetCore.Common
{
/// <summary>
/// 自定义异常信息
/// </summary>
public class MyApiException : Exception
{
/// <summary>
/// 异常
/// </summary>
/// <param name="message"></param>
public MyApiException(string message)
{
Msg = message;
}
/// <summary>
/// </summary>
/// <param name="message"></param>
/// <param name="errcode"></param>
public MyApiException(string message, string errcode)
{
Msg = message;
ErrCode = errcode;
}
/// <summary>
/// </summary>
/// <param name="message"></param>
/// <param name="success"></param>
/// <param name="errcode"></param>
public MyApiException(string message, bool success, string errcode)
{
Msg = message;
Success = success;
ErrCode = errcode;
}
/// <summary>
/// </summary>
public MyApiException()
{
}
/// <summary>
/// </summary>
/// <param name="info"></param>
/// <param name="context"></param>
protected MyApiException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
/// <summary>
/// </summary>
/// <param name="message"></param>
/// <param name="innerException"></param>
public MyApiException(string message, Exception innerException) : base(message, innerException)
{
Msg = message;
throw innerException;
}
/// <summary>
/// </summary>
/// <param name="message"></param>
/// <param name="errcode"></param>
/// <param name="innerException"></param>
public MyApiException(string message, string errcode, Exception innerException) : base(message, innerException)
{
Msg = message;
ErrCode = errcode;
throw innerException;
}
/// <summary>
/// 异常消息
/// </summary>
public string Msg { get; set; }
/// <summary>
/// 成功状态
/// </summary>
public bool Success { get; set; }
/// <summary>
/// 提示代码
/// </summary>
public string ErrCode { get; set; }
}
}

64
Znyc.Cloudcar.Admin.AspNetCore/Common/Permission.cs

@ -0,0 +1,64 @@
using System;
using System.Linq;
using Znyc.Cloudcar.Admin.Commons.Cache;
using Znyc.Cloudcar.Admin.Commons.Json;
using Znyc.Cloudcar.Admin.Security.Dtos;
namespace Znyc.Cloudcar.Admin.AspNetCore.Common
{
/// <summary>
/// 权限控制
/// </summary>
public static class Permission
{
/// <summary>
/// 判断当前用户是否拥有某功能点的权限
/// </summary>
/// <param name="functionCode">功能编码code</param>
/// <param name="userId">用户id</param>
/// <returns></returns>
public static bool HasFunction(string functionCode, int userId)
{
bool hasFunction = false;
if (!string.IsNullOrEmpty(userId.ToString()))
{
if (string.IsNullOrEmpty(functionCode))
{
hasFunction = true;
}
else
{
System.Collections.Generic.List<MenuOutputDto> listFunction = new CacheHelper().Get("User_Function_" + userId).ToJson()
.ToList<MenuOutputDto>();
if (listFunction != null && listFunction.Count(t => t.EnCode == functionCode) > 0)
{
hasFunction = true;
}
}
}
return hasFunction;
}
/// <summary>
/// 判断是否为系统管理员或超级管理员
/// </summary>
/// <returns>true:系统管理员或超级管理员,false:不是系统管理员或超级管理员</returns>
/// <param name="AdminCurrentUser"></param>
/// <returns></returns>
public static bool IsAdmin(AdminCurrentUser AdminCurrentUser)
{
bool blnIsAdmin = false;
if (AdminCurrentUser != null)
{
if (AdminCurrentUser.Account == "admin" ||
AdminCurrentUser.Role.Contains("administrators", StringComparison.Ordinal))
{
return true;
}
}
return blnIsAdmin;
}
}
}

20
Znyc.Cloudcar.Admin.AspNetCore/Common/SessionObject.cs

@ -0,0 +1,20 @@
using Znyc.Cloudcar.Admin.Security.Entitys;
namespace Znyc.Cloudcar.Admin.WebApi.Common
{
/// <summary>
/// SessionObject是登录之后,给客户端传回的对象
/// </summary>
public class SessionObject
{
/// <summary>
/// SessionKey
/// </summary>
public string SessionKey { get; set; }
/// <summary>
/// 当前登录的用户的信息
/// </summary>
public AdminUserEntity LogonUser { get; set; }
}
}

253
Znyc.Cloudcar.Admin.AspNetCore/Mvc/ApiController.cs

@ -0,0 +1,253 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Security.Claims;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Unicode;
using Znyc.Cloudcar.Admin.AspNetCore.Common;
using Znyc.Cloudcar.Admin.AspNetCore.Entitys;
using Znyc.Cloudcar.Admin.AspNetCore.Mvc;
using Znyc.Cloudcar.Admin.AspNetCore.Mvc.Filter;
using Znyc.Cloudcar.Admin.Commons.Cache;
using Znyc.Cloudcar.Admin.Commons.Entitys;
using Znyc.Cloudcar.Admin.Commons.Extensions;
using Znyc.Cloudcar.Admin.Commons.Helpers;
using Znyc.Cloudcar.Admin.Commons.Json;
using Znyc.Cloudcar.Admin.Commons.Log;
using Znyc.Cloudcar.Admin.Commons.Pages;
using Znyc.Cloudcar.Admin.Security.Dtos;
namespace Znyc.Cloudcar.Admin.AspNetCore.Controllers
{
/// <summary>
/// WebApi控制器基类
/// </summary>
[ApiController]
[EnableCors("Cors")]
public class ApiController : Controller
{
/// <summary>
/// 当前登录的用户属性
/// </summary>
public AdminCurrentUser CurrentUser;
#region
/// <summary>
/// 重写基类在Action执行之前的事情
/// 根据token获得当前用户,允许匿名的不需要获取用户
/// </summary>
/// <param name="context">重写方法的参数</param>
public override void OnActionExecuting(ActionExecutingContext context)
{
try
{
ControllerActionDescriptor controllerActionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;
//匿名访问,不需要token认证、签名和登录
Attribute allowanyone =
controllerActionDescriptor.MethodInfo.GetCustomAttribute(typeof(AllowAnonymousAttribute), true);
if (allowanyone != null)
{
return;
}
CommonResult result = new CommonResult();
//需要token认证
string authHeader = context.HttpContext.Request.Headers["Authorization"]; //Header中的token
if (string.IsNullOrEmpty(authHeader))
{
result.ErrCode = "40004";
result.ErrMsg = ErrCode.err40004;
context.Result = ToJsonContent(result);
}
else
{
string token = string.Empty;
if (authHeader != null && authHeader.StartsWith("Bearer ", StringComparison.Ordinal))
{
token = authHeader.Substring(7);
}
TokenProvider tokenProvider = new TokenProvider();
result = tokenProvider.ValidateToken(token);
//token验证失败
if (!result.Success)
{
context.Result = ToJsonContent(result);
}
else
{
#region 是否需要验证用户登录以及相关的功能权限
//是否需要用户登录
Attribute isDefined =
controllerActionDescriptor.MethodInfo.GetCustomAttribute(
typeof(NoPermissionRequiredAttribute));
//不需要登录
if (isDefined != null)
{
return;
}
//需要登录和验证功能权限
if (result.ResData != null)
{
List<Claim> claimlist = result.ResData as List<Claim>;
string userId = claimlist[3].Value;
Claim[] claims =
{
new(ZnycClaimTypes.UserId, userId),
new(ZnycClaimTypes.UserName, claimlist[2].Value),
new(ZnycClaimTypes.Role, claimlist[4].Value)
};
ClaimsIdentity identity = new ClaimsIdentity(claims);
ClaimsPrincipal principal = new ClaimsPrincipal(identity);
context.HttpContext.User = principal;
CacheHelper yuebonCacheHelper = new CacheHelper();
AdminCurrentUser user = yuebonCacheHelper.Get<AdminCurrentUser>("login_user_" + userId);
if (user != null)
{
CurrentUser = user;
}
bool isAdmin = Permission.IsAdmin(user);
if (!isAdmin)
{
IEnumerable<FunctionAuthorizeAttribute> authorizeAttributes = controllerActionDescriptor.MethodInfo
.GetCustomAttributes(typeof(FunctionAuthorizeAttribute), true)
.OfType<FunctionAuthorizeAttribute>();
if (authorizeAttributes.FirstOrDefault() != null)
{
string function = authorizeAttributes.First().Function;
if (!string.IsNullOrEmpty(function))
{
string functionCode = controllerActionDescriptor.ControllerName + "/" + function;
bool bl = Permission.HasFunction(functionCode, userId.ToInt());
if (!bl)
{
result.ErrCode = "40006";
result.ErrMsg = ErrCode.err40006;
context.Result = ToJsonContent(result);
}
}
}
}
}
else
{
result.ErrCode = "40008";
result.ErrMsg = ErrCode.err40008;
context.Result = ToJsonContent(result);
}
#endregion 是否需要验证用户登录以及相关的功能权限
}
}
}
catch (Exception ex)
{
Log4NetHelper.Error("", ex);
}
}
#endregion
/// <summary>
/// 把object对象转换为ContentResult
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
[HttpPost]
[Route("api/ToJsonContent")]
protected IActionResult ToJsonContent(object obj)
{
return Content(obj.ToJson());
}
/// <summary>
/// 把object对象转换为ContentResult
/// </summary>
/// <param name="obj">转换对象</param>
/// <param name="isNull">是否忽略空值</param>
/// <returns></returns>
[HttpPost]
[Route("api/ToJsonContent")]
protected IActionResult ToJsonContent(object obj, bool isNull = false)
{
JsonSerializerOptions options = new JsonSerializerOptions
{
WriteIndented = true, //格式化json字符串
AllowTrailingCommas = true, //可以结尾有逗号
IgnoreNullValues = true, //可以有空值,转换json去除空值属性
IgnoreReadOnlyProperties = true, //忽略只读属性
PropertyNameCaseInsensitive = true, //忽略大小写
Encoder = JavaScriptEncoder.Create(UnicodeRanges.All)
};
options.Converters.Add(new DateTimeJsonConverter());
return Content(JsonSerializer.Serialize(obj, options));
}
/// <summary>
/// 根据Request参数获取分页对象数据
/// </summary>
/// <returns></returns>
protected virtual PagerInfo GetPagerInfo()
{
int pageSize = Request.Query["length"].ToString() == null ? 1 : Request.Query["length"].ToString().ToInt();
int pageIndex = 1;
string currentPage = Request.Query["CurrentPage"].ToString();
if (string.IsNullOrWhiteSpace(currentPage))
{
string start = Request.Query["start"].ToString();
if (!string.IsNullOrWhiteSpace(start))
{
pageIndex = start.ToInt() / pageSize + 1;
}
}
else
{
pageIndex = currentPage.ToInt();
}
PagerInfo pagerInfo = new PagerInfo
{
CurrenetPageIndex = pageIndex,
PageSize = pageSize
};
return pagerInfo;
}
/// <summary>
/// 获取token
/// </summary>
/// <returns></returns>
[HttpGet("GetToken")]
[HiddenApi]
public string GetToken()
{
string token = HttpContext.Request.Query["Token"];
if (!string.IsNullOrEmpty(token))
{
return token;
}
string authHeader = HttpContext.Request.Headers["Authorization"]; //Header中的token
if (authHeader != null && authHeader.StartsWith("Bearer"))
{
token = authHeader.Substring("Bearer ".Length).Trim();
return token;
}
string cookie = HttpContext.Request.Cookies["Token"];
return cookie == null ? string.Empty : cookie;
}
}
}

373
Znyc.Cloudcar.Admin.AspNetCore/Mvc/AreaApiController.cs

@ -0,0 +1,373 @@
using Microsoft.AspNetCore.Mvc;
using System;
using Znyc.Cloudcar.Admin.Commons.Entitys;
using Znyc.Cloudcar.Admin.Commons.IServices;
namespace Znyc.Cloudcar.Admin.AspNetCore.Controllers
{
/// <summary>
/// 基本控制器,增删改查
/// </summary>
/// <typeparam name="T">实体类型</typeparam>
/// <typeparam name="TODto">数据输出实体类型</typeparam>
/// <typeparam name="TIDto">数据输入实体类型</typeparam>
/// <typeparam name="TService">Service类型</typeparam>
/// <typeparam name="TKey">主键数据类型</typeparam>
[ApiController]
public abstract class AreaApiController<T, TODto, TIDto, TService, TKey> : ApiController
where T : Entity
where TService : IService<T, TODto, TKey>
where TODto : class
where TIDto : class
where TKey : IEquatable<TKey>
{
#region 属性变量
/// <summary>
/// 服务接口
/// </summary>
public TService _service;
#endregion 属性变量
#region 构造函数及常用
/// <summary>
/// 构造方法
/// </summary>
/// <param name="service"></param>
public AreaApiController(TService service)
{
_service = service;
}
#endregion 构造函数及常用
#region 查询单个实体
// /// <summary>
// /// 根据主键Id获取一个对象信息
// /// </summary>
// /// <param name="id">主键Id</param>
// /// <returns></returns>
// [HttpGet("GetById")]
//// [FunctionAuthorize("")]
// //[NoPermissionRequired]
// [AllowAnonymous]
// public virtual async Task<CommonResult<TODto>> GetById(TKey id)
// {
// var result = new CommonResult<TODto>();
// var info = await _service.GetOutDtoAsync(id);
// if (info != null)
// {
// result.ErrCode = ErrCode.successCode;
// result.ResData = info;
// }
// else
// {
// result.ErrMsg = ErrCode.err50001;
// result.ErrCode = "50001";
// }
// return result;
// }
#endregion 查询单个实体
//#region 返回集合的接口
///// <summary>
///// 根据条件查询数据库,并返回对象集合(用于分页数据显示)
///// </summary>
///// <param name="search">查询条件</param>
///// <returns>指定对象的集合</returns>
//[HttpPost("FindWithPager")]
//[FunctionAuthorize("List")]
//public virtual CommonResult<PageResult<TODto>> FindWithPager(SearchInputDto<T> search)
//{
// var result = new CommonResult<PageResult<TODto>>();
// result.ResData = _service.FindWithPager(search);
// result.ErrCode = ErrCode.successCode;
// return result;
//}
///// <summary>
///// 根据条件查询数据库,并返回对象集合(用于分页数据显示)
///// </summary>
///// <param name="search"></param>
///// <returns></returns>
//[HttpPost("FindWithPagerAsync")]
//[FunctionAuthorize("List")]
//public virtual async Task<CommonResult<PageResult<TODto>>> FindWithPagerAsync(SearchInputDto<T> search)
//{
// var result = new CommonResult<PageResult<TODto>>();
// result.ResData = await _service.FindWithPagerAsync(search);
// result.ErrCode = ErrCode.successCode;
// return result;
//}
/// <summary>
/// 获取所有可用的
/// </summary>
/// <returns></returns>
//[HttpGet("GetAllEnable")]
//[FunctionAuthorize("List")]
//public virtual async Task<CommonResult<List<TODto>>> GetAllEnable()
//{
// var result = new CommonResult<List<TODto>>();
// var list = await _service.GetAllByIsNotDeleteAndEnabledMarkAsync();
// var resultList = list.MapTo<TODto>();
// result.ResData = resultList;
// result.ErrCode = ErrCode.successCode;
// result.ErrMsg = ErrCode.err0;
// return result;
//}
#region 公共添加、修改、删除、软删除接口
/// <summary>
/// 在插入数据前对数据的修改操作
/// </summary>
/// <param name="info"></param>
/// <returns></returns>
protected virtual void OnBeforeInsert(T info)
{
//留给子类对参数对象进行修改
}
/// <summary>
/// 在更新数据前对数据的修改操作
/// </summary>
/// <param name="info"></param>
/// <returns></returns>
protected virtual void OnBeforeUpdate(T info)
{
//留给子类对参数对象进行修改
}
/// <summary>
/// 在软删除数据前对数据的修改操作
/// </summary>
/// <param name="info"></param>
/// <returns></returns>
protected virtual void OnBeforeSoftDelete(T info)
{
//留给子类对参数对象进行修改
}
///// <summary>
///// 异步新增数据,无效
///// </summary>
///// <param name="tinfo"></param>
///// <returns></returns>
//[HttpPost("Insert")]
//[FunctionAuthorize("Add")]
//public virtual async Task<IActionResult> InsertAsync(TIDto tinfo)
//{
// var result = new CommonResult();
// var info = tinfo.MapTo<T>();
// OnBeforeInsert(info);
// long ln = await _service.InsertAsync(info).ConfigureAwait(false);
// if (ln > 0)
// {
// result.ErrCode = ErrCode.successCode;
// result.ErrMsg = ErrCode.err0;
// }
// else
// {
// result.ErrMsg = ErrCode.err43001;
// result.ErrCode = "43001";
// }
// return ToJsonContent(result);
//}
///// <summary>
///// 异步更新数据,需要在业务模块控制器重写该方法,否则更新无效
///// </summary>
///// <param name="inInfo"></param>
///// <returns></returns>
//[HttpPost("Update")]
//[FunctionAuthorize("Edit")]
//public virtual async Task<IActionResult> UpdateAsync(TIDto inInfo)
//{
// var result = new CommonResult();
// return ToJsonContent(result);
//}
///// <summary>
///// 物理删除
///// </summary>
///// <param name="id">主键Id</param>
//[HttpDelete("Delete")]
//[FunctionAuthorize("Delete")]
//public virtual IActionResult Delete(TKey id)
//{
// var result = new CommonResult();
// var bl = _service.Delete(id);
// if (bl)
// {
// result.ErrCode = ErrCode.successCode;
// result.ErrMsg = ErrCode.err0;
// }
// else
// {
// result.ErrMsg = ErrCode.err43003;
// result.ErrCode = "43003";
// }
// return ToJsonContent(result);
//}
///// <summary>
///// 异步物理删除
///// </summary>
///// <param name="id">主键Id</param>
//[HttpDelete("DeleteAsync")]
//[FunctionAuthorize("Delete")]
//public virtual async Task<IActionResult> DeleteAsync(TKey id)
//{
// var result = new CommonResult();
// var bl = await _service.DeleteAsync(id).ConfigureAwait(false);
// if (bl)
// {
// result.ErrCode = ErrCode.successCode;
// result.ErrMsg = ErrCode.err0;
// }
// else
// {
// result.ErrMsg = ErrCode.err43003;
// result.ErrCode = "43003";
// }
// return ToJsonContent(result);
//}
///// <summary>
///// 异步批量物理删除
///// </summary>
///// <param name="info"></param>
//[HttpDelete("DeleteBatchAsync")]
//[FunctionAuthorize("Delete")]
//public virtual async Task<IActionResult> DeleteBatchAsync(DeletesInputDto info)
//{
// var result = new CommonResult();
// var where = string.Empty;
// if (typeof(TKey) == typeof(string))
// @where = "id in ('" + info.Ids.Join(",").Trim(',').Replace(",", "','") + "')";
// else if (typeof(TKey) == typeof(int)) @where = "id in (" + info.Ids.Join(",") + ")";
// if (!string.IsNullOrEmpty(where))
// {
// var bl = await _service.DeleteBatchWhereAsync(where).ConfigureAwait(false);
// if (bl)
// {
// result.ErrCode = ErrCode.successCode;
// result.ErrMsg = ErrCode.err0;
// }
// else
// {
// result.ErrMsg = ErrCode.err43003;
// result.ErrCode = "43003";
// }
// }
// return ToJsonContent(result);
//}
///// <summary>
///// 软删除信息
///// </summary>
///// <param name="id">主键Id</param>
///// <param name="bltag">删除标识,默认为1:即设为删除,0:未删除</param>
//[HttpPost("DeleteSoft")]
//[FunctionAuthorize("DeleteSoft")]
//public virtual IActionResult DeleteSoft(TKey id, string bltag = "1")
//{
// var result = new CommonResult();
// var bl = false;
// if (bltag == "0") bl = true;
// var blResult = _service.DeleteSoft(bl, id, CurrentUser.UserId);
// if (blResult)
// {
// result.ErrCode = ErrCode.successCode;
// result.ErrMsg = ErrCode.err0;
// }
// else
// {
// result.ErrMsg = ErrCode.err43002;
// result.ErrCode = "43002";
// }
// return ToJsonContent(result);
//}
/// <summary>
/// 异步软删除信息
/// </summary>
/// <param name="id">主键Id</param>
/// <param name="bltag">删除标识,默认为1:即设为删除,0:未删除</param>
//[HttpDelete("DeleteSoftAsync")]
//[FunctionAuthorize("DeleteSoft")]
//public virtual async Task<IActionResult> DeleteSoftAsync(TKey id, string bltag = "1")
//{
// var result = new CommonResult();
// var bl = false;
// if (bltag == "0") bl = true;
// var blResult = await _service.DeleteSoftAsync(bl, id, CurrentUser.UserId);
// if (blResult)
// {
// result.ErrCode = ErrCode.successCode;
// result.ErrMsg = ErrCode.err0;
// }
// else
// {
// result.ErrMsg = ErrCode.err43002;
// result.ErrCode = "43002";
// }
// return ToJsonContent(result);
//}
///// <summary>
///// 异步批量软删除信息
///// </summary>
///// <param name="info"></param>
///// <returns></returns>
//[HttpDelete("DeleteSoftBatchAsync")]
//[FunctionAuthorize("DeleteSoft")]
//public virtual async Task<IActionResult> DeleteSoftBatchAsync(UpdateEnableViewModel info)
//{
// var result = new CommonResult();
// var where = string.Empty;
// if (typeof(int) == typeof(string))
// @where = "id in ('" + info.Ids.Join(",").Trim(',').Replace(",", "','") + "')";
// else if (typeof(int) == typeof(int)) @where = "id in (" + info.Ids.Join(",") + ")";
// if (!string.IsNullOrEmpty(where))
// {
// var bl = false;
// if (info.Flag == "1") bl = true;
// var blResult = await _service.DeleteSoftBatchAsync(bl, where, CurrentUser.UserId);
// if (blResult)
// {
// result.ErrCode = ErrCode.successCode;
// result.ErrMsg = ErrCode.err0;
// }
// else
// {
// result.ErrMsg = ErrCode.err43002;
// result.ErrCode = "43002";
// }
// }
// return ToJsonContent(result);
//}
#endregion 公共添加、修改、删除、软删除接口
// #endregion
}
}

149
Znyc.Cloudcar.Admin.AspNetCore/Mvc/Filter/ActionFilter.cs

@ -0,0 +1,149 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Newtonsoft.Json;
using StackExchange.Profiling;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Threading.Tasks;
using Znyc.Cloudcar.Admin.Commons.Core.App;
using Znyc.Cloudcar.Admin.Commons.Entitys;
using Znyc.Cloudcar.Admin.Security.Dtos;
using Znyc.Cloudcar.Admin.Security.Entitys;
using Znyc.Cloudcar.Admin.Security.IServices;
namespace Znyc.Cloudcar.Admin.AspNetCore.Mvc.Filter
{
/// <summary>
/// </summary>
public class ActionFilter : IAsyncActionFilter
{
private readonly IOperationLogsService _operationLogsService = App.GetService<IOperationLogsService>();
/// <summary>
/// </summary>
/// <param name="context"></param>
/// <param name="next"></param>
/// <returns></returns>
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
MiniProfiler profiler = MiniProfiler.StartNew("StartNew");
using (profiler.Step("Level1"))
{
// WriteLog(profiler);
//执行Action
await next();
}
// await WriteOperationLog(context, next);
//WriteLog(profiler);
}
public async Task WriteOperationLog(ActionExecutingContext context, ActionExecutionDelegate next)
{
Stopwatch sw = new Stopwatch();
sw.Start();
ActionExecutedContext actionExecutedContext = await next();
sw.Stop();
//操作参数
string args = JsonConvert.SerializeObject(context.ActionArguments);
//操作结果
// var result = JsonConvert.SerializeObject(actionResult?.Value);
try
{
OperationLogsEntity input = new OperationLogsEntity
{
UserName = new AdminCurrentUser().Name ?? "",
CreatedTime = DateTime.Now,
OperationTime = DateTime.Now,
CreatedUserId = new AdminCurrentUser().UserId,
RequestUrl = args,
OS = "PC",
IP = new AdminCurrentUser().CurrentLoginIP ?? "",
City = new AdminCurrentUser().IPAddressName ?? "",
CRUD = context.HttpContext.Request.Method.ToLower(),
Browser = "",
RequertData = "",
UserAgent = context.RouteData.Values["controller"].ToString()
// context.HttpContext.Request.Method.ToLower(),
// context.ActionDescriptor.AttributeRouteInfo.Template.ToLower(),
// sw.ElapsedMilliseconds
};
if (actionExecutedContext.Result is ObjectResult result && result.Value is CommonResult res)
{
input.RequertData = res.ErrCode;
}
//input.Msg = res.Success;
await _operationLogsService.InsertAsync(input);
}
catch (Exception)
{
// _logger.LogError("操作日志插入异常:{@ex}", ex);
}
}
/// <summary>
/// sql跟踪
/// 下载:MiniProfiler.AspNetCore
/// </summary>
/// <param name="profiler"></param>
private void WriteLog(MiniProfiler profiler)
{
if (profiler?.Root != null)
{
Timing root = profiler.Root;
if (root.HasChildren)
{
GetSqlLog(root.Children);
}
}
}
/// <summary>
/// 递归获取MiniProfiler内容
/// </summary>
/// <param name="chil"></param>
private void GetSqlLog(List<Timing> chil)
{
chil.ForEach(chill =>
{
if (chill.CustomTimings?.Count > 0)
{
StringBuilder logSql = new StringBuilder();
foreach (KeyValuePair<string, List<CustomTiming>> customTiming in chill.CustomTimings)
{
int i = 1;
customTiming.Value?.ForEach(value =>
{
if (value.ExecuteType != "OpenAsync" && !value.CommandString.Contains("Connection"))
{
logSql.Append(
$"【{customTiming.Key}{i++}】{value.CommandString} 耗时 :{value.DurationMilliseconds} ms,状态 :{(value.Errored ? "" : "")}");
}
});
}
Console.WriteLine($"sql+{logSql}");
//var logEntity = new Log();
//logEntity.Date = logEntity.CreatedTime = DateTime.Now;
//logEntity.Type = "SQL";
//logEntity.Result = true;
//logEntity.Description = logSql.ToString();
//_logService.Insert(logEntity);
}
else
{
if (chill.Children != null)
{
GetSqlLog(chill.Children);
}
}
});
}
}
}

102
Znyc.Cloudcar.Admin.AspNetCore/Mvc/Filter/ExceptionHandlingAttribute.cs

@ -0,0 +1,102 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Security.Claims;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Unicode;
using Yitter.IdGenerator;
using Znyc.Cloudcar.Admin.AspNetCore.Common;
using Znyc.Cloudcar.Admin.Commons.Cache;
using Znyc.Cloudcar.Admin.Commons.Entitys;
using Znyc.Cloudcar.Admin.Commons.Helpers;
using Znyc.Cloudcar.Admin.Commons.Json;
using Znyc.Cloudcar.Admin.Commons.Log;
using Znyc.Cloudcar.Admin.Security.Dtos;
using Znyc.Cloudcar.Admin.Security.Entitys;
using Znyc.Cloudcar.Admin.Security.Repositories;
namespace Znyc.Cloudcar.Admin.AspNetCore.Mvc.Filter
{
/// <summary>
/// 表示一个特性,该特性用于全局捕获程序运行异常信息。
/// </summary>
public class ExceptionHandlingAttribute : ExceptionFilterAttribute
{
private readonly ExceptionsLogsRepository _exceptionsLogs = new();
/// <summary>
/// </summary>
/// <param name="context"></param>
public override void OnException(ExceptionContext context)
{
Exception exception = context.Exception;
AdminCurrentUser CurrentUser = new AdminCurrentUser();
string requestPath = context.HttpContext.Request.Path.ToString();
string queryString = context.HttpContext.Request.QueryString.ToString();
Type type = MethodBase.GetCurrentMethod().DeclaringType;
string exDesc = requestPath + queryString;
Log4NetHelper.Error(type, "全局捕获程序运行异常信息\n\r" + exDesc, context.Exception);
CommonResult result = new CommonResult();
if (exception is MyApiException myApiex)
{
context.HttpContext.Response.StatusCode = 200;
context.ExceptionHandled = true;
result.ErrMsg = myApiex.Msg;
result.ErrCode = myApiex.ErrCode;
}
else
{
result.ErrMsg = "程序异常,服务端出现异常![异常消息]" + exception.Message;
result.ErrCode = "500";
}
JsonSerializerOptions options = new JsonSerializerOptions
{
WriteIndented = true, //格式化json字符串
AllowTrailingCommas = true, //可以结尾有逗号
//IgnoreNullValues = true, //可以有空值,转换json去除空值属性
IgnoreReadOnlyProperties = true, //忽略只读属性
PropertyNameCaseInsensitive = true, //忽略大小写
//PropertyNamingPolicy = JsonNamingPolicy.CamelCase //命名方式是默认还是CamelCase
Encoder = JavaScriptEncoder.Create(UnicodeRanges.All)
};
options.Converters.Add(new DateTimeJsonConverter("yyyy-MM-dd HH:mm:ss"));
context.Result = new JsonResult(result, options);
ExceptionsLogsEntity exceptionsLogs = new ExceptionsLogsEntity();
IEnumerable<ClaimsIdentity> identities = context.HttpContext.User.Identities;
ClaimsIdentity claimsIdentity = identities.First();
if (claimsIdentity != null)
{
List<Claim> claimlist = claimsIdentity.Claims as List<Claim>;
if (claimlist.Count > 0)
{
string userId = claimlist[0].Value;
CacheHelper cacheHelper = new CacheHelper();
AdminCurrentUser user = cacheHelper.Get("login_user_" + userId).ToJson().ToObject<AdminCurrentUser>();
if (user != null)
{
CurrentUser = user;
}
exceptionsLogs.Id = YitIdHelper.NextId();
exceptionsLogs.AppDomainName = requestPath;
exceptionsLogs.ErrorPage = queryString;
exceptionsLogs.UserName = CurrentUser.Name;
exceptionsLogs.IP = CurrentUser.CurrentLoginIP;
exceptionsLogs.ExceptionType = exception.GetType().Name;
exceptionsLogs.Message = exception.Message;
exceptionsLogs.StackTrace = exception.StackTrace;
exceptionsLogs.ExceptionTime = exceptionsLogs.CreatedTime = DateTime.Now;
exceptionsLogs.CreatedTime = DateTime.Now;
exceptionsLogs.CreatedUserId = CurrentUser.UserId;
exceptionsLogs.IsDeleted = false;
_exceptionsLogs.Insert(exceptionsLogs);
}
}
}
}
}

74
Znyc.Cloudcar.Admin.AspNetCore/Mvc/Filter/FunctionAuthorizationFilter.cs

@ -0,0 +1,74 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using System.Reflection;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Unicode;
using Znyc.Cloudcar.Admin.AspNetCore.Entitys;
using Znyc.Cloudcar.Admin.Commons.Entitys;
using Znyc.Cloudcar.Admin.Commons.Helpers;
namespace Znyc.Cloudcar.Admin.AspNetCore.Mvc
{
/// <summary>
/// 功能权限授权验证
/// </summary>
public class FunctionAuthorizationFilter : AuthorizeAttribute, IAuthorizationFilter
{
/// <summary>
/// 授权验证
/// </summary>
/// <param name="context"></param>
public void OnAuthorization(AuthorizationFilterContext context)
{
ControllerActionDescriptor controllerActionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;
//匿名访问,不需要token认证、签名和登录
System.Attribute allowanyone =
controllerActionDescriptor.MethodInfo.GetCustomAttribute(typeof(AllowAnonymousAttribute), true);
if (allowanyone != null)
{
return;
}
CommonResult result = new CommonResult();
JsonSerializerOptions options = new JsonSerializerOptions
{
WriteIndented = true, //格式化json字符串
AllowTrailingCommas = true, //可以结尾有逗号
//IgnoreNullValues = true, //可以有空值,转换json去除空值属性
IgnoreReadOnlyProperties = true, //忽略只读属性
PropertyNameCaseInsensitive = true, //忽略大小写
//PropertyNamingPolicy = JsonNamingPolicy.CamelCase //命名方式是默认还是CamelCase
Encoder = JavaScriptEncoder.Create(UnicodeRanges.All)
};
options.Converters.Add(new DateTimeJsonConverter());
//需要token认证
string authHeader = context.HttpContext.Request.Headers["Authorization"]; //Header中的token
if (string.IsNullOrEmpty(authHeader))
{
result.ErrCode = "40004";
result.ErrMsg = ErrCode.err40004;
context.Result = new JsonResult(result, options);
}
else
{
string token = string.Empty;
if (authHeader != null)
{
token = authHeader.Substring(7);
}
TokenProvider tokenProvider = new TokenProvider();
result = tokenProvider.ValidateToken(token);
//token验证失败
if (!result.Success)
{
context.Result = new JsonResult(result, options);
}
}
}
}
}

26
Znyc.Cloudcar.Admin.AspNetCore/Mvc/Filter/FunctionAuthorizeAttribute.cs

@ -0,0 +1,26 @@
using Microsoft.AspNetCore.Mvc.Filters;
using System;
namespace Znyc.Cloudcar.Admin.AspNetCore.Mvc
{
/// <summary>
/// 功能权限属性配置
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class FunctionAuthorizeAttribute : ActionFilterAttribute
{
/// <summary>
/// 构造函数
/// </summary>
/// <param name="function">功能代码</param>
public FunctionAuthorizeAttribute(string function)
{
Function = function;
}
/// <summary>
/// 功能权限
/// </summary>
public string Function { get; set; }
}
}

49
Znyc.Cloudcar.Admin.AspNetCore/Mvc/Filter/HiddenApiAttribute.cs

@ -0,0 +1,49 @@
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using System;
using System.Linq;
using System.Reflection;
namespace Znyc.Cloudcar.Admin.AspNetCore.Mvc
{
/// <summary>
/// 隐藏接口,不生成到swagger文档展示
/// </summary>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public class HiddenApiAttribute : Attribute
{
}
/// <summary>
/// 隐藏接口,不生成到swagger文档展示
/// </summary>
public class HiddenApiFilter : IDocumentFilter
{
/// <summary>
/// 实现Apply方法
/// </summary>
/// <param name="swaggerDoc"></param>
/// <param name="documentFilterContext"></param>
public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext documentFilterContext)
{
foreach (Microsoft.AspNetCore.Mvc.ApiExplorer.ApiDescription apiDescription in documentFilterContext.ApiDescriptions)
{
if (apiDescription.TryGetMethodInfo(out MethodInfo methodInfo))
{
if (methodInfo.GetCustomAttributes<HiddenApiAttribute>().OfType<HiddenApiAttribute>()
.Any())
{
string key = "/" + apiDescription.RelativePath.TrimEnd('/');
if (key.Contains("?"))
{
int idx = key.IndexOf("?", StringComparison.Ordinal);
key = key.Substring(0, idx);
}
swaggerDoc.Paths.Remove(key);
}
}
}
}
}
}

18
Znyc.Cloudcar.Admin.AspNetCore/Mvc/Filter/NoPermissionRequiredAttribute.cs

@ -0,0 +1,18 @@
using Microsoft.AspNetCore.Mvc.Filters;
namespace Znyc.Cloudcar.Admin.AspNetCore.Mvc.Filter
{
/// <summary>
/// 不需要权限验证,不需要登录
/// </summary>
public class NoPermissionRequiredAttribute : ActionFilterAttribute
{
/// <summary>
/// </summary>
/// <param name="filterContext"></param>
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
}
}
}

55
Znyc.Cloudcar.Admin.AspNetCore/Mvc/Filter/SwaggerFileUploadFilter.cs

@ -0,0 +1,55 @@
using Microsoft.AspNetCore.Http;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using System;
using System.Linq;
namespace Znyc.Cloudcar.Admin.AspNetCore.Mvc.Filter
{
/// <summary>
/// Swagger 上传文件过滤器
/// </summary>
public class SwaggerFileUploadFilter : IOperationFilter
{
/// <summary>
/// 应用过滤器
/// </summary>
/// <param name="operation"></param>
/// <param name="context"></param>
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
{
#region 文件上传处理
if (!context.ApiDescription.HttpMethod.Equals("POST", StringComparison.OrdinalIgnoreCase) &&
!context.ApiDescription.HttpMethod.Equals("PUT", StringComparison.OrdinalIgnoreCase))
{
return;
}
System.Collections.Generic.List<Microsoft.AspNetCore.Mvc.Abstractions.ParameterDescriptor> fileParameters = context.ApiDescription.ActionDescriptor.Parameters
.Where(n => n.ParameterType == typeof(IFormFile)).ToList();
if (fileParameters.Count < 0)
{
return;
}
foreach (Microsoft.AspNetCore.Mvc.Abstractions.ParameterDescriptor fileParameter in fileParameters)
{
OpenApiParameter parameter = operation.Parameters.Single(n => n.Name == fileParameter.Name);
operation.Parameters.Remove(parameter);
operation.Parameters.Add(new OpenApiParameter
{
Name = parameter.Name,
In = ParameterLocation.Header, //"formData",
Description = parameter.Description,
Required = parameter.Required,
Content = parameter.Content
});
}
#endregion 文件上传处理
}
}
}
}

220
Znyc.Cloudcar.Admin.AspNetCore/Mvc/TokenProvider.cs

@ -0,0 +1,220 @@
using IdentityModel;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Znyc.Cloudcar.Admin.AspNetCore.Common;
using Znyc.Cloudcar.Admin.AspNetCore.Entitys;
using Znyc.Cloudcar.Admin.Commons.Core.App;
using Znyc.Cloudcar.Admin.Commons.Entitys;
using Znyc.Cloudcar.Admin.Commons.Log;
using Znyc.Cloudcar.Admin.Commons.Options;
using Znyc.Cloudcar.Admin.Security.Entitys;
using Znyc.Cloudcar.Admin.Security.IServices;
namespace Znyc.Cloudcar.Admin.AspNetCore.Mvc
{
/// <summary>
/// Token令牌提供类
/// </summary>
public class TokenProvider
{
private readonly JwtOption _jwtModel = App.GetService<JwtOption>();
private readonly IRoleService _roleService = App.GetService<IRoleService>();
/// <summary>
/// 构造函数
/// </summary>
public TokenProvider()
{
}
/// <summary>
/// 构造函数,初花jwtmodel
/// </summary>
/// <param name="jwtModel"></param>
public TokenProvider(JwtOption jwtModel)
{
_jwtModel = jwtModel;
}
/// <summary>
/// 直接通过appid和加密字符串获取访问令牌接口
/// </summary>
/// <param name="granttype">获取access_token填写client_credential</param>
/// <param name="appid">用户唯一凭证AppId</param>
/// <param name="secret">用户唯一凭证密钥,即appsecret</param>
/// <returns></returns>
public TokenResult GenerateToken(string granttype, string appid, string secret)
{
byte[] keyByteArray = Encoding.UTF8.GetBytes(secret);
SymmetricSecurityKey signingKey = new SymmetricSecurityKey(keyByteArray);
DateTime expires = DateTime.UtcNow.Add(TimeSpan.FromMinutes(_jwtModel.Expiration));
SigningCredentials signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256);
SecurityTokenDescriptor tokenDescripor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[]
{
new(JwtClaimTypes.Audience, appid),
new Claim(JwtClaimTypes.Issuer, _jwtModel.Issuer),
new Claim(JwtClaimTypes.Subject, GrantType.ClientCredentials)
}, granttype),
Expires = expires,
//对称秘钥SymmetricSecurityKey
//签名证书(秘钥,加密算法)SecurityAlgorithms
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(keyByteArray),
SecurityAlgorithms.HmacSha256Signature)
};
JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
SecurityToken token = tokenHandler.CreateToken(tokenDescripor);
string tokenString = tokenHandler.WriteToken(token);
TokenResult result = new TokenResult
{
AccessToken = tokenString,
ExpiresIn = (int)TimeSpan.FromMinutes(_jwtModel.Expiration).TotalMinutes
};
return result;
}
/// <summary>
/// 检查用户的Token有效性
/// </summary>
/// <param name="token">token令牌</param>
/// <returns></returns>
public CommonResult ValidateToken(string token)
{
//返回的结果对象
CommonResult result = new CommonResult();
if (!string.IsNullOrEmpty(token))
{
try
{
JwtSecurityToken jwtToken = new JwtSecurityTokenHandler().ReadJwtToken(token);
if (jwtToken != null)
{
#region 检查令牌对象内容
DateTime now = DateTime.UtcNow;
DateTime refreshTime = jwtToken.ValidFrom;
refreshTime = refreshTime.Add(TimeSpan.FromMinutes(_jwtModel.refreshJwtTime));
if (now > refreshTime && jwtToken.Issuer == _jwtModel.Issuer)
{
result.ErrMsg = ErrCode.err40005;
result.ErrCode = "40005";
}
else
{
if (jwtToken.Subject == GrantType.Password)
{
List<Claim> claimlist = jwtToken?.Payload.Claims as List<Claim>;
result.ResData = claimlist;
}
result.ErrMsg = ErrCode.err0;
result.ErrCode = ErrCode.successCode;
}
#endregion 检查令牌对象内容
}
else
{
result.ErrMsg = ErrCode.err40004;
result.ErrCode = "40004";
}
}
catch (Exception ex)
{
Log4NetHelper.Error("验证token异常", ex);
throw new MyApiException(ErrCode.err40004, "40004");
}
}
else
{
result.ErrMsg = ErrCode.err40004;
result.ErrCode = "40004";
}
return result;
}
/// <summary>
/// 根据用户获取token
/// </summary>
/// <param name="userInfo">用户信息</param>
/// <param name="appid">应用Id</param>
/// <returns></returns>
public TokenResult LoginToken(AdminUserEntity userInfo, string appid)
{
JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
byte[] key = Encoding.UTF8.GetBytes(_jwtModel.Secret);
DateTime authTime = DateTime.UtcNow; //授权时间
DateTime expires = authTime.Add(TimeSpan.FromMinutes(_jwtModel.Expiration)); //过期时间
SecurityTokenDescriptor tokenDescripor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[]
{
new(JwtClaimTypes.Audience, appid),
new Claim(JwtClaimTypes.Issuer, _jwtModel.Issuer),
new Claim(JwtClaimTypes.Name, userInfo.Account),
new Claim(JwtClaimTypes.Id, userInfo.Id.ToString()),
new Claim(JwtClaimTypes.Role, _roleService.GetRoleEnCode(userInfo.RoleId.ToString())),
new Claim(JwtClaimTypes.Subject, GrantType.Password)
}),
Expires = expires,
//对称秘钥SymmetricSecurityKey
//签名证书(秘钥,加密算法)SecurityAlgorithms
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key),
SecurityAlgorithms.HmacSha256Signature)
};
SecurityToken token = tokenHandler.CreateToken(tokenDescripor);
string tokenString = tokenHandler.WriteToken(token);
TokenResult result = new TokenResult
{
AccessToken = tokenString,
ExpiresIn = (int)TimeSpan.FromMinutes(_jwtModel.Expiration).TotalMinutes
};
return result;
}
/// <summary>
/// 根据登录用户获取token
/// </summary>
/// <param name="userInfo">用户信息</param>
/// <param name="appid">应用Id</param>
/// <returns></returns>
public TokenResult GetUserToken(AdminUserEntity userInfo, string appid)
{
JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
byte[] key = Encoding.UTF8.GetBytes(_jwtModel.Secret);
DateTime authTime = DateTime.UtcNow; //授权时间
DateTime expires = authTime.Add(TimeSpan.FromMinutes(_jwtModel.Expiration)); //过期时间
SecurityTokenDescriptor tokenDescripor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[]
{
new(JwtClaimTypes.Audience, appid),
new Claim(JwtClaimTypes.Issuer, _jwtModel.Issuer),
new Claim(JwtClaimTypes.Name, userInfo.Account),
new Claim(JwtClaimTypes.Id, userInfo.Id.ToString()),
new Claim(JwtClaimTypes.Role, userInfo.RoleId.ToString()),
new Claim(JwtClaimTypes.Subject, GrantType.Password)
}),
Expires = expires,
//对称秘钥SymmetricSecurityKey
//签名证书(秘钥,加密算法)SecurityAlgorithms
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key),
SecurityAlgorithms.HmacSha256Signature)
};
SecurityToken token = tokenHandler.CreateToken(tokenDescripor);
string tokenString = tokenHandler.WriteToken(token);
TokenResult result = new TokenResult
{
AccessToken = tokenString,
ExpiresIn = (int)TimeSpan.FromMinutes(_jwtModel.Expiration).TotalMinutes
};
return result;
}
}
}

16
Znyc.Cloudcar.Admin.AspNetCore/Properties/PublishProfiles/FolderProfile.pubxml

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<DeleteExistingFiles>False</DeleteExistingFiles>
<ExcludeApp_Data>False</ExcludeApp_Data>
<LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<PublishProvider>FileSystem</PublishProvider>
<PublishUrl>bin\Release\net6.0\publish\</PublishUrl>
<WebPublishMethod>FileSystem</WebPublishMethod>
</PropertyGroup>
</Project>

24
Znyc.Cloudcar.Admin.AspNetCore/ViewModel/DBConnResult.cs

@ -0,0 +1,24 @@
using System;
using System.Runtime.Serialization;
namespace Znyc.Cloudcar.Admin.AspNetCore.ViewModel
{
/// <summary>
/// 数据库连接返回结果实体
/// </summary>
[Serializable]
public class DBConnResult
{
/// <summary>
/// 未加密字符串
/// </summary>
[DataMember]
public string ConnStr { get; set; }
/// <summary>
/// 数据库名称
/// </summary>
[DataMember]
public string EncryptConnStr { get; set; }
}
}

48
Znyc.Cloudcar.Admin.AspNetCore/ViewModel/DbConnInfo.cs

@ -0,0 +1,48 @@
using System;
using System.Runtime.Serialization;
namespace Znyc.Cloudcar.Admin.AspNetCore.ViewModel
{
/// <summary>
/// 数据库连接字符串实体
/// </summary>
[Serializable]
public class DbConnInfo
{
/// <summary>
/// 访问地址
/// </summary>
[DataMember]
public string DbAddress { get; set; }
/// <summary>
/// 端口,默认SQLServer为1433;Mysql为3306
/// </summary>
[DataMember]
public int DbPort { get; set; }
/// <summary>
/// 数据库名称
/// </summary>
[DataMember]
public string DbName { get; set; }
/// <summary>
/// 用户名
/// </summary>
[DataMember]
public string DbUserName { get; set; }
/// <summary>
/// 访问密码
/// </summary>
[DataMember]
public string DbPassword { get; set; }
/// <summary>
/// 数据库类型
/// </summary>
[DataMember]
public string DbType { get; set; }
}
}

34
Znyc.Cloudcar.Admin.AspNetCore/ViewModel/SearchModel.cs

@ -0,0 +1,34 @@
using System;
using System.Runtime.Serialization;
using Znyc.Cloudcar.Admin.Commons.Pages;
namespace Znyc.Cloudcar.Admin.AspNetCore.ViewModel
{
/// <summary>
/// 查询条件公共实体类
/// </summary>
[Serializable]
[DataContract]
public class SearchModel : PagerInfo
{
/// <summary>
/// 关键词
/// </summary>
public string Keywords { get; set; }
/// <summary>
/// 编码/代码
/// </summary>
public string EnCode { get; set; }
/// <summary>
/// 排序方式 默认asc
/// </summary>
public string Order { get; set; }
/// <summary>
/// 排序字段 默认Id
/// </summary>
public string Sort { get; set; }
}
}

22
Znyc.Cloudcar.Admin.AspNetCore/ViewModel/UpdateEnableViewModel.cs

@ -0,0 +1,22 @@
using System;
namespace Znyc.Cloudcar.Admin.AspNetCore.ViewModel
{
/// <summary>
/// 批量更新操作传入参数,如设为禁用、有效、软删除;
/// 物理删除操作是Flag无效不用传参
/// </summary>
[Serializable]
public class UpdateEnableViewModel
{
/// <summary>
/// 主键Id集合
/// </summary>
public dynamic[] Ids { get; set; }
/// <summary>
/// 有效标识,默认为1:即设为无效,0:有效
/// </summary>
public string Flag { get; set; }
}
}

27
Znyc.Cloudcar.Admin.AspNetCore/ViewModel/VueCascaderModel.cs

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
namespace Znyc.Cloudcar.Admin.AspNetCore.ViewModel
{
/// <summary>
/// Vue Cascader 级联选择模型
/// </summary>
[Serializable]
public class VueCascaderModel
{
/// <summary>
/// 值
/// </summary>
public string value { get; set; }
/// <summary>
/// 显示名称
/// </summary>
public string label { get; set; }
/// <summary>
/// 子集
/// </summary>
public List<VueCascaderModel> children { get; set; }
}
}

90
Znyc.Cloudcar.Admin.AspNetCore/ViewModel/VuexMenusTree.cs

@ -0,0 +1,90 @@
using System;
using System.Collections.Generic;
namespace Znyc.Cloudcar.Admin.AspNetCore.ViewModel
{
/// <summary>
/// Vuex菜单模型
/// </summary>
[Serializable]
public class VuexMenusTreeModel
{
/// <summary>
/// 字符串,对应当前路由的路径,总是解析为绝对路径
/// </summary>
public string path { get; set; }
/// <summary>
/// 命名视图组件
/// </summary>
public string component { get; set; }
/// <summary>
/// 重定向地址,在面包屑中点击会重定向去的地址
/// </summary>
public string redirect { get; set; }
/// <summary>
/// 设定路由的名字,一定要填写不然使用keep-alive时会出现各种问题
/// </summary>
public string name { get; set; }
/// <summary>
/// 在根路由设置权限,这样它下面所以的子路由都继承了这个权限
/// </summary>
public Meta meta { get; set; }
/// <summary>
/// 子菜单
/// </summary>
public List<VuexMenusTreeModel> children { get; set; }
}
/// <summary>
/// VuexMenus路由模型
/// </summary>
[Serializable]
public class VuexMenus
{
/// <summary>
/// 访问路径
/// </summary>
public string path { get; set; }
/// <summary>
/// 对应模块
/// </summary>
public string component { get; set; }
/// <summary>
/// 重定向地址,在面包屑中点击会重定向去的地址
/// </summary>
public string redirect { get; set; }
/// <summary>
/// 设定路由的名字,一定要填写不然使用keep-alive时会出现各种问题
/// </summary>
public string name { get; set; }
/// <summary>
/// </summary>
public Meta meta { get; set; }
}
/// <summary>
/// 路由元信息模型
/// </summary>
[Serializable]
public class Meta
{
/// <summary>
/// 设置该路由在侧边栏和面包屑中展示的名字
/// </summary>
public string title { get; set; }
/// <summary>
/// 设置该路由的图标
/// </summary>
public string icon { get; set; }
}
}

73
Znyc.Cloudcar.Admin.AspNetCore/Znyc.Cloudcar.Admin.AspNetCore.csproj

@ -0,0 +1,73 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ApplicationIcon />
<OutputType>Library</OutputType>
<StartupObject />
<Company></Company>
<Copyright></Copyright>
<Product></Product>
<Authors>Znyc.Admin</Authors>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<IsPackable>true</IsPackable>
<Version>1.0</Version>
<PackageReleaseNotes></PackageReleaseNotes>
<RunAnalyzersDuringLiveAnalysis>true</RunAnalyzersDuringLiveAnalysis>
<RunAnalyzersDuringBuild>true</RunAnalyzersDuringBuild>
<PackageProjectUrl></PackageProjectUrl>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<AssemblyName>Znyc.Recruitment.Admin.AspNetCore</AssemblyName>
<RepositoryUrl></RepositoryUrl>
<AssemblyVersion>1.3.1.37</AssemblyVersion>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DocumentationFile>bin\Release\Znyc.Recruitment.Admin.AspNetCore.xml</DocumentationFile>
<OutputPath>bin\Release\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<OutputPath>bin\Debug\</OutputPath>
<DocumentationFile>bin\Debug\Znyc.Recruitment.Admin.AspNetCore.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Controllers\**" />
<Compile Remove="SSO\**" />
<Content Remove="Controllers\**" />
<Content Remove="SSO\**" />
<EmbeddedResource Remove="Controllers\**" />
<EmbeddedResource Remove="SSO\**" />
<None Remove="Controllers\**" />
<None Remove="SSO\**" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Common\AuthorizeKey.cs" />
<Compile Remove="Mvc\AuthorizeMiddleware.cs" />
<Compile Remove="Mvc\Filter\AdminAuthorizationActionFilter.cs" />
<Compile Remove="Mvc\Filter\NoA.cs" />
<Compile Remove="Mvc\Filter\PermissionRequiredFilter.cs" />
</ItemGroup>
<ItemGroup>
<None Remove="logo.png" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="IdentityModel" Version="5.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Authorization" Version="5.0.8" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="5.0.8" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="5.0.8" />
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="6.12.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.1.4" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.12.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Znyc.Cloudcar.Admin.Commons\Znyc.Cloudcar.Admin.Commons.csproj" />
<ProjectReference Include="..\Znyc.Cloudcar.Admin.Security.Core\Znyc.Cloudcar.Admin.Security.Core.csproj" />
</ItemGroup>
</Project>

23
Znyc.Cloudcar.Admin.Commons/Attributes/AppDbContextFactoryAttribute.cs

@ -0,0 +1,23 @@
using System;
namespace Znyc.Cloudcar.Admin.Commons.Attributes
{
/// <summary>
/// 数据库上下文配置
/// </summary>
public class AppDbContextFactoryAttribute : Attribute
{
/// <summary>
/// </summary>
/// <param name="dbConfigName">数据库配置名称</param>
public AppDbContextFactoryAttribute(string dbConfigName)
{
DbConfigName = dbConfigName;
}
/// <summary>
/// 数据库配置名称
/// </summary>
public string DbConfigName { get; set; }
}
}

39
Znyc.Cloudcar.Admin.Commons/Attributes/ShardingTableAttribute.cs

@ -0,0 +1,39 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace Znyc.Cloudcar.Admin.Commons.Attributes
{
/// <summary>
/// 数据库分表特性
/// </summary>
public class ShardingTableAttribute : TableAttribute
{
/// <summary>
/// </summary>
/// <param name="name"></param>
public ShardingTableAttribute(string name) : base(name)
{
Suffix = "yyyyMMdd";
Splitter = "_";
}
/// <summary>
/// </summary>
/// <param name="name"></param>
/// <param name="splitter"></param>
/// <param name="suffix"></param>
public ShardingTableAttribute(string name, string splitter = "_", string suffix = "yyyyMMdd") : base(name)
{
Suffix = suffix;
}
/// <summary>
/// 分隔符
/// </summary>
public string Splitter { get; set; } = "_";
/// <summary>
/// 分表后缀格式。默认值:_yyyyMMdd
/// </summary>
public string Suffix { get; set; } = "yyyyMMdd";
}
}

12
Znyc.Cloudcar.Admin.Commons/Attributes/UnitOfWorkAttribute.cs

@ -0,0 +1,12 @@
using System;
namespace Znyc.Cloudcar.Admin.Commons.Attributes
{
/// <summary>
/// 工作单元
/// 仅用来做特性标记
/// </summary>
public class UnitOfWorkAttribute : Attribute
{
}
}

406
Znyc.Cloudcar.Admin.Commons/Cache/CacheHelper.cs

@ -0,0 +1,406 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Znyc.Cloudcar.Admin.Commons.Core.App;
namespace Znyc.Cloudcar.Admin.Commons.Cache
{
/// <summary>
/// 缓存操作帮助类
/// </summary>
public class CacheHelper
{
/// <summary>
/// 缓存提供模式
/// </summary>
private static CacheProvider cacheProvider;
/// <summary>
/// 缓存接口
/// </summary>
private readonly ICacheService cacheservice;
/// <summary>
/// </summary>
public CacheHelper()
{
cacheProvider = App.GetService<CacheProvider>();
if (cacheProvider == null)
{
throw new ArgumentNullException(nameof(cacheProvider));
}
cacheservice = App.GetService<ICacheService>();
}
/// <summary>
/// 使用MemoryCache缓存操作
/// </summary>
/// <param name="isMemoryCache">是否使用MemoryCache</param>
public CacheHelper(bool isMemoryCache = false)
{
cacheProvider = App.GetService<CacheProvider>();
if (cacheProvider == null)
{
throw new ArgumentNullException(nameof(cacheProvider));
}
if (isMemoryCache)
{
cacheservice = App.GetService<MemoryCacheService>();
}
else
{
cacheservice = App.GetService<ICacheService>();
}
}
#region 验证缓存项是否存在
/// <summary>
/// 验证缓存项是否存在,TryGetValue 来检测 Key是否存在的
/// </summary>
/// <param name="key">缓存Key</param>
/// <returns></returns>
public bool Exists(string key)
{
return cacheservice.Exists(key);
}
#endregion 验证缓存项是否存在
#region 添加缓存
/// <summary>
/// 添加缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <param name="value">缓存Value</param>
/// <returns></returns>
public bool Add(string key, object value)
{
return cacheservice.Add(key, value);
}
/// <summary>
/// 添加缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <param name="value">缓存Value</param>
/// <param name="expiresSliding">滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>
/// <param name="expiressAbsoulte">绝对过期时长</param>
/// <returns></returns>
public bool Add(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte)
{
return cacheservice.Add(key, value, expiresSliding, expiressAbsoulte);
}
/// <summary>
/// 添加缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <param name="value">缓存Value</param>
/// <param name="expiresIn">缓存时长</param>
/// <param name="isSliding">是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>
/// <returns></returns>
public bool Add(string key, object value, TimeSpan expiresIn, bool isSliding = false)
{
return cacheservice.Add(key, value, expiresIn, isSliding);
}
#endregion 添加缓存
#region 删除缓存
/// <summary>
/// 删除缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <returns></returns>
public bool Remove(string key)
{
return cacheservice.Remove(key);
}
/// <summary>
/// 批量删除缓存
/// </summary>
/// <param name="keys">缓存Key集合</param>
/// <returns></returns>
public void RemoveAll(IEnumerable<string> keys)
{
cacheservice.RemoveAll(keys);
}
/// <summary>
/// 删除匹配到的缓存
/// </summary>
/// <param name="pattern"></param>
/// <returns></returns>
public void RemoveByPattern(string pattern)
{
cacheservice.RemoveByPattern(pattern);
}
/// <summary>
/// 删除所有缓存
/// </summary>
public void RemoveCacheAll()
{
cacheservice.RemoveCacheAll();
}
#endregion 删除缓存
#region 获取缓存
/// <summary>
/// 获取缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <returns></returns>
public T Get<T>(string key) where T : class
{
return cacheservice.Get<T>(key);
}
/// <summary>
/// 获取缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <returns></returns>
public object Get(string key)
{
return cacheservice.Get(key);
}
/// <summary>
/// 获取缓存集合
/// </summary>
/// <param name="keys">缓存Key集合</param>
/// <returns></returns>
public IDictionary<string, object> GetAll(IEnumerable<string> keys)
{
return cacheservice.GetAll(keys);
}
#endregion 获取缓存
#region 修改缓存
/// <summary>
/// 修改缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <param name="value">新的缓存Value</param>
/// <returns></returns>
public bool Replace(string key, object value)
{
return cacheservice.Replace(key, value);
}
/// <summary>
/// 修改缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <param name="value">新的缓存Value</param>
/// <param name="expiresSliding">滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>
/// <param name="expiressAbsoulte">绝对过期时长</param>
/// <returns></returns>
public bool Replace(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte)
{
return cacheservice.Replace(key, value, expiresSliding, expiressAbsoulte);
}
/// <summary>
/// 修改缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <param name="value">新的缓存Value</param>
/// <param name="expiresIn">缓存时长</param>
/// <param name="isSliding">是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>
/// <returns></returns>
public bool Replace(string key, object value, TimeSpan expiresIn, bool isSliding = false)
{
return cacheservice.Replace(key, value, expiresIn, isSliding);
}
#endregion 修改缓存
#region Hash
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <param name="value"></param>
/// <returns></returns>
public bool HSet(string key, string filed, object value)
{
return cacheservice.HSet(key, filed, value);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <param name="value"></param>
/// <returns></returns>
public Task<bool> HSetAsync(string key, string filed, object value)
{
return cacheservice.HSetAsync(key, filed, value);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
public Task<bool> HMSetAsync(string key, object[] value)
{
return cacheservice.HMSetAsync(key, value);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
public bool HMSet(string key, object[] value)
{
return cacheservice.HMSet(key, value);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
public string[] HMGet(string key, string[] filed)
{
return cacheservice.HMGet(key, filed);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
public Task<string[]> HMGetAsync(string key, string filed)
{
return cacheservice.HMGetAsync(key, filed);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
public long HDel(string key, string[] filed)
{
return cacheservice.HDel(key, filed);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
public Task<long> HDelAsync(string key, string filed)
{
return cacheservice.HDelAsync(key, filed);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
public bool HExists(string key, string filed)
{
return cacheservice.HExists(key, filed);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
public Task<bool> HExistsAsync(string key, string filed)
{
return cacheservice.HExistsAsync(key, filed);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
public Task<long> HIncrAsync(string key, string filed)
{
return cacheservice.HIncrByAsync(key, filed);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
public long HIncr(string key, string filed)
{
return cacheservice.HIncrBy(key, filed);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public Task<Dictionary<string, string>> HGetAllAsync(string key)
{
return cacheservice.HGetAllAsync(key);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public Dictionary<string, string> HGetAll(string key)
{
return cacheservice.HGetAll(key);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
public Task<string> HGetAsync(string key, string filed)
{
return cacheservice.HGetAsync(key, filed);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <param name="value"></param>
/// <returns></returns>
public Task<bool> HSetNxAsync(string key, string filed, object value)
{
return cacheservice.HSetNxAsync(key, filed, value);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <param name="value"></param>
/// <returns></returns>
public bool HSetNx(string key, string filed, object value)
{
return cacheservice.HSetNx(key, filed, value);
}
#endregion Hash
}
}

23
Znyc.Cloudcar.Admin.Commons/Cache/CacheProvider.cs

@ -0,0 +1,23 @@
namespace Znyc.Cloudcar.Admin.Commons.Cache
{
/// <summary>
/// 缓存提供模式,使用Redis或MemoryCache
/// </summary>
public class CacheProvider
{
/// <summary>
/// 是否使用Redis
/// </summary>
public bool IsUseRedis { get; set; }
/// <summary>
/// Redis连接
/// </summary>
public string ConnectionString { get; set; }
/// <summary>
/// Redis实例名称
/// </summary>
public string InstanceName { get; set; }
}
}

305
Znyc.Cloudcar.Admin.Commons/Cache/ICacheService.cs

@ -0,0 +1,305 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Znyc.Cloudcar.Admin.Commons.Cache
{
/// <summary>
/// 缓存服务接口
/// </summary>
public interface ICacheService
{
#region 验证缓存项是否存在
/// <summary>
/// 验证缓存项是否存在
/// </summary>
/// <param name="key">缓存Key</param>
/// <returns></returns>
bool Exists(string key);
#endregion 验证缓存项是否存在
#region 添加缓存
/// <summary>
/// 添加缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <param name="value">缓存Value</param>
/// <returns></returns>
bool Add(string key, object value);
/// <summary>
/// 添加缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <param name="value">缓存Value</param>
/// <param name="expiresSliding">滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>
/// <param name="expiressAbsoulte">绝对过期时长</param>
/// <returns></returns>
bool Add(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte);
/// <summary>
/// 添加缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <param name="value">缓存Value</param>
/// <param name="expiresIn">缓存时长</param>
/// <param name="isSliding">是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>
/// <returns></returns>
bool Add(string key, object value, TimeSpan expiresIn, bool isSliding = false);
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <param name="value"></param>
/// <returns></returns>
Task<bool> HashSetAsync(string key, string filed, object value);
/// <summary>
/// 添加缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <param name="value">缓存Value</param>
/// <returns></returns>
Task<bool> AddAsync(string key, object value);
/// <summary>
/// /
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <param name="expiresIn"></param>
/// <param name="isSliding"></param>
/// <returns></returns>
Task<bool> AddAsync(string key, object value, TimeSpan expiresIn, bool isSliding = false);
#endregion 添加缓存
#region 删除缓存
/// <summary>
/// 删除缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <returns></returns>
bool Remove(string key);
/// <summary>
/// 批量删除缓存
/// </summary>
/// <param name="keys">缓存Key集合</param>
/// <returns></returns>
void RemoveAll(IEnumerable<string> keys);
/// <summary>
/// 使用通配符找出所有的key然后逐个删除
/// </summary>
/// <param name="pattern">通配符</param>
void RemoveByPattern(string pattern);
/// <summary>
/// 删除所有缓存
/// </summary>
void RemoveCacheAll();
/// <summary>
/// 删除缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <returns></returns>
Task<bool> RemoveAsync(string key);
#endregion 删除缓存
#region 获取缓存
/// <summary>
/// 获取缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <returns></returns>
T Get<T>(string key) where T : class;
/// <summary>
/// 获取缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <returns></returns>
object Get(string key);
/// <summary>
/// 获取缓存集合
/// </summary>
/// <param name="keys">缓存Key集合</param>
/// <returns></returns>
IDictionary<string, object> GetAll(IEnumerable<string> keys);
#endregion 获取缓存
#region 修改缓存
/// <summary>
/// 修改缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <param name="value">新的缓存Value</param>
/// <returns></returns>
bool Replace(string key, object value);
/// <summary>
/// 修改缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <param name="value">新的缓存Value</param>
/// <param name="expiresSliding">滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>
/// <param name="expiressAbsoulte">绝对过期时长</param>
/// <returns></returns>
bool Replace(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte);
/// <summary>
/// 修改缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <param name="value">新的缓存Value</param>
/// <param name="expiresIn">缓存时长</param>
/// <param name="isSliding">是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>
/// <returns></returns>
bool Replace(string key, object value, TimeSpan expiresIn, bool isSliding = false);
#endregion 修改缓存
#region Hash
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <param name="value"></param>
/// <returns></returns>
bool HSet(string key, string filed, object value);
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <param name="value"></param>
/// <returns></returns>
Task<bool> HSetAsync(string key, string filed, object value);
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
Task<bool> HMSetAsync(string key, object[] value);
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
bool HMSet(string key, object[] value);
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
string[] HMGet(string key, string[] filed);
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
Task<string[]> HMGetAsync(string key, string filed);
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
long HDel(string key, string[] filed);
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
Task<long> HDelAsync(string key, string filed);
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
bool HExists(string key, string filed);
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
Task<bool> HExistsAsync(string key, string filed);
/// <summary>
/// 自增
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
Task<long> HIncrByAsync(string key, string filed);
/// <summary>
/// 自增
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
long HIncrBy(string key, string filed);
/// <summary>
/// 获取所有
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
Task<Dictionary<string, string>> HGetAllAsync(string key);
/// <summary>
/// 获取所有
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
Dictionary<string, string> HGetAll(string key);
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
Task<string> HGetAsync(string key, string filed);
/// <summary>
/// 设置一个键值对(不存在,则创建;否则,修改)
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <param name="value"></param>
/// <returns></returns>
Task<bool> HSetNxAsync(string key, string filed, object value);
/// <summary>
/// 设置一个键值对(不存在,则创建;否则,修改)
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <param name="value"></param>
/// <returns></returns>
bool HSetNx(string key, string filed, object value);
#endregion
}
}

594
Znyc.Cloudcar.Admin.Commons/Cache/MemoryCacheService.cs

@ -0,0 +1,594 @@
using Microsoft.Extensions.Caching.Memory;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace Znyc.Cloudcar.Admin.Commons.Cache
{
/// <summary>
/// MemoryCache缓存操作
/// </summary>
public class MemoryCacheService : ICacheService
{
/// <summary>
/// </summary>
protected IMemoryCache _cache;
/// <summary>
/// </summary>
/// <param name="cache"></param>
public MemoryCacheService(IMemoryCache cache)
{
_cache = cache;
}
#region 验证缓存项是否存在
/// <summary>
/// 验证缓存项是否存在,TryGetValue 来检测 Key是否存在的
/// </summary>
/// <param name="key">缓存Key</param>
/// <returns></returns>
public bool Exists(string key)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
return _cache.TryGetValue(key, out object cached);
}
#endregion 验证缓存项是否存在
public Task<bool> AddAsync(string key, object value)
{
throw new NotImplementedException();
}
public Task<bool> AddAsync(string key, object value, TimeSpan expiresIn, bool isSliding = false)
{
throw new NotImplementedException();
}
public Task<bool> RemoveAsync(string key)
{
throw new NotImplementedException();
}
/// <summary>
/// </summary>
public void Dispose()
{
if (_cache != null)
{
_cache.Dispose();
}
GC.SuppressFinalize(this);
}
#region 添加缓存
/// <summary>
/// 添加缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <param name="value">缓存Value</param>
/// <returns></returns>
public bool Add(string key, object value)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
_cache.Set(key, value);
return Exists(key);
}
/// <summary>
/// 添加缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <param name="value">缓存Value</param>
/// <param name="expiresSliding">滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>
/// <param name="expiressAbsoulte">绝对过期时长</param>
/// <returns></returns>
public bool Add(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
_cache.Set(key, value,
new MemoryCacheEntryOptions()
.SetSlidingExpiration(expiresSliding)
.SetAbsoluteExpiration(expiressAbsoulte)
);
return Exists(key);
}
/// <summary>
/// 添加缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <param name="value">缓存Value</param>
/// <param name="expiresIn">缓存时长</param>
/// <param name="isSliding">是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>
/// <returns></returns>
public bool Add(string key, object value, TimeSpan expiresIn, bool isSliding = false)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
if (isSliding)
{
_cache.Set(key, value,
new MemoryCacheEntryOptions()
.SetSlidingExpiration(expiresIn)
);
}
else
{
_cache.Set(key, value,
new MemoryCacheEntryOptions()
.SetAbsoluteExpiration(expiresIn)
);
}
return Exists(key);
}
public Task<bool> HashSetAsync(string key, string filed, object value)
{
throw new NotImplementedException();
}
#endregion 添加缓存
#region 删除缓存
/// <summary>
/// 删除缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <returns></returns>
public bool Remove(string key)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
_cache.Remove(key);
return !Exists(key);
}
/// <summary>
/// 批量删除缓存
/// </summary>
/// <param name="keys">缓存Key集合</param>
/// <returns></returns>
public void RemoveAll(IEnumerable<string> keys)
{
if (keys == null)
{
throw new ArgumentNullException(nameof(keys));
}
keys.ToList().ForEach(item => _cache.Remove(item));
}
/// <summary>
/// 删除所有缓存
/// </summary>
public void RemoveCacheAll()
{
List<string> l = GetCacheKeys();
foreach (string s in l)
{
Remove(s);
}
}
/// <summary>
/// 删除匹配到的缓存
/// </summary>
/// <param name="pattern"></param>
/// <returns></returns>
public void RemoveByPattern(string pattern)
{
IList<string> l = SearchCacheRegex(pattern);
foreach (string s in l)
{
Remove(s);
}
}
/// <summary>
/// 搜索 匹配到的缓存
/// </summary>
/// <param name="pattern"></param>
/// <returns></returns>
public IList<string> SearchCacheRegex(string pattern)
{
List<string> cacheKeys = GetCacheKeys();
List<string> l = cacheKeys.Where(k => Regex.IsMatch(k, pattern)).ToList();
return l.AsReadOnly();
}
#endregion 删除缓存
#region 获取缓存
/// <summary>
/// 获取缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <returns></returns>
public T Get<T>(string key) where T : class
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
return _cache.Get(key) as T;
}
/// <summary>
/// 获取缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <returns></returns>
public object Get(string key)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
return _cache.Get(key);
}
/// <summary>
/// 获取缓存集合
/// </summary>
/// <param name="keys">缓存Key集合</param>
/// <returns></returns>
public IDictionary<string, object> GetAll(IEnumerable<string> keys)
{
if (keys == null)
{
throw new ArgumentNullException(nameof(keys));
}
Dictionary<string, object> dict = new Dictionary<string, object>();
keys.ToList().ForEach(item => dict.Add(item, _cache.Get(item)));
return dict;
}
/// <summary>
/// 获取所有缓存键
/// </summary>
/// <returns></returns>
public List<string> GetCacheKeys()
{
const BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic;
object entries = _cache.GetType().GetField("_entries", flags).GetValue(_cache);
IDictionary cacheItems = entries as IDictionary;
List<string> keys = new List<string>();
if (cacheItems == null)
{
return keys;
}
foreach (DictionaryEntry cacheItem in cacheItems)
{
keys.Add(cacheItem.Key.ToString());
}
return keys;
}
#endregion 获取缓存
#region 修改缓存
/// <summary>
/// 修改缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <param name="value">新的缓存Value</param>
/// <returns></returns>
public bool Replace(string key, object value)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
if (Exists(key))
{
if (!Remove(key))
{
return false;
}
}
return Add(key, value);
}
/// <summary>
/// 修改缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <param name="value">新的缓存Value</param>
/// <param name="expiresSliding">滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>
/// <param name="expiressAbsoulte">绝对过期时长</param>
/// <returns></returns>
public bool Replace(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
if (Exists(key))
{
if (!Remove(key))
{
return false;
}
}
return Add(key, value, expiresSliding, expiressAbsoulte);
}
/// <summary>
/// 修改缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <param name="value">新的缓存Value</param>
/// <param name="expiresIn">缓存时长</param>
/// <param name="isSliding">是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>
/// <returns></returns>
public bool Replace(string key, object value, TimeSpan expiresIn, bool isSliding = false)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
if (Exists(key))
{
if (!Remove(key))
{
return false;
}
}
return Add(key, value, expiresIn, isSliding);
}
#endregion 修改缓存
#region Hash
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <param name="value"></param>
/// <returns></returns>
public bool HSet(string key, string filed, object value)
{
return RedisHelper.HSet(key, filed, value);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <param name="value"></param>
/// <returns></returns>
public Task<bool> HSetAsync(string key, string filed, object value)
{
return RedisHelper.HSetAsync(key, filed, value);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
public Task<bool> HMSetAsync(string key, object[] value)
{
return RedisHelper.HMSetAsync(key, value);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
public bool HMSet(string key, object[] value)
{
return RedisHelper.HMSet(key, value);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
public string[] HMGet(string key, string[] filed)
{
return RedisHelper.HMGet(key, filed);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
public Task<string[]> HMGetAsync(string key, string filed)
{
return RedisHelper.HMGetAsync(key, filed);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
public long HDel(string key, string[] filed)
{
return RedisHelper.HDel(key, filed);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
public Task<long> HDelAsync(string key, string filed)
{
return RedisHelper.HDelAsync(key, filed);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
public bool HExists(string key, string filed)
{
return RedisHelper.HExists(key, filed);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
public Task<bool> HExistsAsync(string key, string filed)
{
return RedisHelper.HExistsAsync(key, filed);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
public Task<long> HIncrByAsync(string key, string filed)
{
return RedisHelper.HIncrByAsync(key, filed);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
public long HIncrBy(string key, string filed)
{
return RedisHelper.HIncrBy(key, filed);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public Task<Dictionary<string, string>> HGetAllAsync(string key)
{
return RedisHelper.HGetAllAsync(key);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public Dictionary<string, string> HGetAll(string key)
{
return RedisHelper.HGetAll(key);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
public async Task<string> HGetAsync(string key, string filed)
{
return await RedisHelper.HGetAsync(key, filed);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <param name="value"></param>
/// <returns></returns>
public Task<bool> HSetNxAsync(string key, string filed, object value)
{
return RedisHelper.HSetNxAsync(key, filed, value);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <param name="value"></param>
/// <returns></returns>
public bool HSetNx(string key, string filed, object value)
{
return RedisHelper.HSetNx(key, filed, value);
}
#endregion Hash
}
}

634
Znyc.Cloudcar.Admin.Commons/Cache/RedisCacheService.cs

@ -0,0 +1,634 @@
using Microsoft.Extensions.Caching.StackExchangeRedis;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace Znyc.Cloudcar.Admin.Commons.Cache
{
/// <summary>
/// Redis缓存操作
/// </summary>
public class RedisCacheService : ICacheService
{
/// <summary>
/// </summary>
private readonly ConnectionMultiplexer _connection;
/// <summary>
/// </summary>
private readonly string _instance;
private readonly JsonSerializerOptions _jsonOptions;
/// <summary>
/// </summary>
protected IDatabase _cache;
/// <summary>
/// </summary>
/// <param name="options"></param>
/// <param name="database"></param>
/// <param name="jsonOptions"></param>
public RedisCacheService(RedisCacheOptions options, JsonSerializerOptions jsonOptions, int database = 0)
{
_connection = ConnectionMultiplexer.Connect(options.Configuration);
_cache = _connection.GetDatabase(database);
_instance = options.InstanceName;
_jsonOptions = jsonOptions;
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public string GetKeyForRedis(string key)
{
return _instance + key;
}
public void Dispose()
{
if (_connection != null)
{
_connection.Dispose();
}
GC.SuppressFinalize(this);
}
#region 验证缓存项是否存在
/// <summary>
/// 验证缓存项是否存在
/// </summary>
/// <param name="key">缓存Key</param>
/// <returns></returns>
public bool Exists(string key)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
return _cache.KeyExists(GetKeyForRedis(key));
}
/// <summary>
/// 验证缓存项是否存在
/// </summary>
/// <param name="key">缓存Key</param>
/// <returns></returns>
public Task<bool> ExistsAsync(string key)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
return _cache.KeyExistsAsync(GetKeyForRedis(key));
}
#endregion 验证缓存项是否存在
#region 添加缓存
/// <summary>
/// 添加缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <param name="value">缓存Value</param>
/// <returns></returns>
public bool Add(string key, object value)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
return _cache.StringSet(GetKeyForRedis(key),
Encoding.UTF8.GetBytes(JsonSerializer.Serialize(value, _jsonOptions)));
}
/// <summary>
/// 添加缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <param name="value">缓存Value</param>
/// <param name="expiresSliding">滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间,Redis中无效)</param>
/// <param name="expiressAbsoulte">绝对过期时长</param>
/// <returns></returns>
public bool Add(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
return _cache.StringSet(GetKeyForRedis(key),
Encoding.UTF8.GetBytes(JsonSerializer.Serialize(value, _jsonOptions)), expiressAbsoulte);
}
/// <summary>
/// 添加缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <param name="value">缓存Value</param>
/// <param name="expiresIn">缓存时长</param>
/// <param name="isSliding">是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间,Redis中无效)</param>
/// <returns></returns>
public bool Add(string key, object value, TimeSpan expiresIn, bool isSliding = false)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
return _cache.StringSet(GetKeyForRedis(key),
Encoding.UTF8.GetBytes(JsonSerializer.Serialize(value, _jsonOptions)), expiresIn);
}
public Task<bool> AddAsync(string key, object value)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
return _cache.StringSetAsync(GetKeyForRedis(key),
Encoding.UTF8.GetBytes(JsonSerializer.Serialize(value, _jsonOptions)));
}
public Task<bool> AddAsync(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
return _cache.StringSetAsync(GetKeyForRedis(key),
Encoding.UTF8.GetBytes(JsonSerializer.Serialize(value, _jsonOptions)), expiressAbsoulte);
}
public Task<bool> AddAsync(string key, object value, TimeSpan expiresIn, bool isSliding = false)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
return _cache.StringSetAsync(GetKeyForRedis(key),
Encoding.UTF8.GetBytes(JsonSerializer.Serialize(value, _jsonOptions)), expiresIn);
}
public Task<bool> HashSetAsync(string key, string filed, object value)
{
return _cache.HashSetAsync(GetKeyForRedis(key),
Encoding.UTF8.GetBytes(JsonSerializer.Serialize(filed, _jsonOptions)),
Encoding.UTF8.GetBytes(JsonSerializer.Serialize(value, _jsonOptions)));
}
#endregion 添加缓存
#region 删除缓存
/// <summary>
/// 删除缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <returns></returns>
public bool Remove(string key)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
return _cache.KeyDelete(GetKeyForRedis(key));
}
/// <summary>
/// 批量删除缓存
/// </summary>
/// <param name="key">缓存Key集合</param>
/// <returns></returns>
public void RemoveAll(IEnumerable<string> keys)
{
if (keys == null)
{
throw new ArgumentNullException(nameof(keys));
}
keys.ToList().ForEach(item => Remove(item));
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public Task<bool> RemoveAsync(string key)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
return _cache.KeyDeleteAsync(GetKeyForRedis(key));
}
public Task RemoveAllAsync(IEnumerable<int> keys)
{
//if (keys == null)
//{
throw new ArgumentNullException(nameof(keys));
//}
//keys.ToList().ForEach(item => RemoveAsync(item));
}
/// <summary>
/// 使用通配符找出所有的key然后逐个删除
/// </summary>
/// <param name="pattern">通配符</param>
public virtual void RemoveByPattern(string pattern)
{
foreach (System.Net.EndPoint ep in _connection.GetEndPoints())
{
IServer server = _connection.GetServer(ep);
IEnumerable<RedisKey> keys = server.Keys(pattern: "*" + pattern + "*", database: _cache.Database);
foreach (RedisKey key in keys)
{
_cache.KeyDelete(key);
}
}
}
/// <summary>
/// 删除所有缓存
/// </summary>
public void RemoveCacheAll()
{
RemoveByPattern("");
}
#endregion 删除缓存
#region 获取缓存
/// <summary>
/// 获取缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <returns></returns>
public T Get<T>(string key) where T : class
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
RedisValue value = _cache.StringGet(GetKeyForRedis(key));
if (!value.HasValue)
{
return default;
}
return JsonSerializer.Deserialize<T>(value, _jsonOptions);
}
/// <summary>
/// 获取缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <returns></returns>
public object Get(string key)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
RedisValue value = _cache.StringGet(GetKeyForRedis(key));
if (!value.HasValue)
{
return null;
}
return JsonSerializer.Deserialize<object>(value, _jsonOptions);
//string json = value.ToString();
//return Newtonsoft.Json.JsonConvert.DeserializeObject(json);
}
/// <summary>
/// 获取缓存集合
/// </summary>
/// <param name="keys">缓存Key集合</param>
/// <returns></returns>
public IDictionary<string, object> GetAll(IEnumerable<string> keys)
{
if (keys == null)
{
throw new ArgumentNullException(nameof(keys));
}
Dictionary<string, object> dict = new Dictionary<string, object>();
keys.ToList().ForEach(item => dict.Add(item, Get(GetKeyForRedis(item))));
return dict;
}
public Task<T> GetAsync<T>(string key) where T : class
{
throw new NotImplementedException();
}
public Task<object> GetAsync(string key)
{
throw new NotImplementedException();
}
public Task<IDictionary<string, object>> GetAllAsync(IEnumerable<int> keys)
{
throw new ArgumentNullException(nameof(keys));
}
#endregion 获取缓存
#region 修改缓存
/// <summary>
/// 修改缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <param name="value">新的缓存Value</param>
/// <returns></returns>
public bool Replace(string key, object value)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
if (Exists(key))
{
if (!Remove(key))
{
return false;
}
}
return Add(key, value);
}
/// <summary>
/// 修改缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <param name="value">新的缓存Value</param>
/// <param name="expiresSliding">滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>
/// <param name="expiressAbsoulte">绝对过期时长</param>
/// <returns></returns>
public bool Replace(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
if (Exists(key))
{
if (!Remove(key))
{
return false;
}
}
return Add(key, value, expiresSliding, expiressAbsoulte);
}
/// <summary>
/// 修改缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <param name="value">新的缓存Value</param>
/// <param name="expiresIn">缓存时长</param>
/// <param name="isSliding">是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>
/// <returns></returns>
public bool Replace(string key, object value, TimeSpan expiresIn, bool isSliding = false)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
if (Exists(key))
{
if (!Remove(key))
{
return false;
}
}
return Add(key, value, expiresIn, isSliding);
}
public Task<bool> ReplaceAsync(string key, object value)
{
throw new NotImplementedException();
}
public Task<bool> ReplaceAsync(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte)
{
throw new NotImplementedException();
}
public Task<bool> ReplaceAsync(string key, object value, TimeSpan expiresIn, bool isSliding = false)
{
throw new NotImplementedException();
}
#endregion 修改缓存
#region Hash
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <param name="value"></param>
/// <returns></returns>
public bool HSet(string key, string filed, object value)
{
return RedisHelper.HSet(key, filed, value);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <param name="value"></param>
/// <returns></returns>
public Task<bool> HSetAsync(string key, string filed, object value)
{
return RedisHelper.HSetAsync(key, filed, value);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
public Task<bool> HMSetAsync(string key, object[] value)
{
return RedisHelper.HMSetAsync(key, value);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
public bool HMSet(string key, object[] value)
{
return RedisHelper.HMSet(key, value);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
public string[] HMGet(string key, string[] filed)
{
return RedisHelper.HMGet(key, filed);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
public Task<string[]> HMGetAsync(string key, string filed)
{
return RedisHelper.HMGetAsync(key, filed);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
public long HDel(string key, string[] filed)
{
return RedisHelper.HDel(key, filed);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
public Task<long> HDelAsync(string key, string filed)
{
return RedisHelper.HDelAsync(key, filed);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
public bool HExists(string key, string filed)
{
return RedisHelper.HExists(key, filed);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
public Task<bool> HExistsAsync(string key, string filed)
{
return RedisHelper.HExistsAsync(key, filed);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
public Task<long> HIncrByAsync(string key, string filed)
{
return RedisHelper.HIncrByAsync(key, filed);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
public long HIncrBy(string key, string filed)
{
return RedisHelper.HIncrBy(key, filed);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public Task<Dictionary<string, string>> HGetAllAsync(string key)
{
return RedisHelper.HGetAllAsync(key);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public Dictionary<string, string> HGetAll(string key)
{
return RedisHelper.HGetAll(key);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <returns></returns>
public async Task<string> HGetAsync(string key, string filed)
{
return await RedisHelper.HGetAsync(key, filed);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <param name="value"></param>
/// <returns></returns>
public Task<bool> HSetNxAsync(string key, string filed, object value)
{
return RedisHelper.HSetNxAsync(key, filed, value);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <param name="filed"></param>
/// <param name="value"></param>
/// <returns></returns>
public bool HSetNx(string key, string filed, object value)
{
return RedisHelper.HSetNx(key, filed, value);
}
#endregion Hash
}
}

235
Znyc.Cloudcar.Admin.Commons/Commons.csproj

@ -0,0 +1,235 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<Authors>Yuebon</Authors>
<Company>上海越邦网络科技有限公司</Company>
<Product>YuebonNetCore开发框架基础库</Product>
<Description>YuebonNetCore开发框架基础库</Description>
<Copyright>上海越邦网络科技有限公司 版权所有</Copyright>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageProjectUrl>https://gitee.com/yuebon/YuebonNetCore</PackageProjectUrl>
<Version>1.3.1.32</Version>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<PackageReleaseNotes></PackageReleaseNotes>
<PackageIconUrl></PackageIconUrl>
<RepositoryUrl>https://gitee.com/yuebon/YuebonNetCore</RepositoryUrl>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageIcon>logo.png</PackageIcon>
<AssemblyVersion>1.3.1.32</AssemblyVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DocumentationFile>bin\Debug\ZNYC.Admin.Commons.xml</DocumentationFile>
<OutputPath>bin\Debug\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<OutputPath>bin\Release\</OutputPath>
<DocumentationFile>bin\Release\ZNYC.Admin.Commons.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<Compile Remove="AutoMapper\**" />
<Compile Remove="Dependency\**" />
<Compile Remove="Entity\**" />
<Compile Remove="Exceptions\**" />
<Compile Remove="Filter\**" />
<Compile Remove="Finders\**" />
<Compile Remove="Middlewares\**" />
<Compile Remove="Reflection\**" />
<EmbeddedResource Remove="AutoMapper\**" />
<EmbeddedResource Remove="Dependency\**" />
<EmbeddedResource Remove="Entity\**" />
<EmbeddedResource Remove="Exceptions\**" />
<EmbeddedResource Remove="Filter\**" />
<EmbeddedResource Remove="Finders\**" />
<EmbeddedResource Remove="Middlewares\**" />
<EmbeddedResource Remove="Reflection\**" />
<None Remove="AutoMapper\**" />
<None Remove="Dependency\**" />
<None Remove="Entity\**" />
<None Remove="Exceptions\**" />
<None Remove="Filter\**" />
<None Remove="Finders\**" />
<None Remove="Middlewares\**" />
<None Remove="Reflection\**" />
<None Include="..\..\LICENSE">
<Pack>True</Pack>
<PackagePath></PackagePath>
</None>
<None Include="..\..\logo.png">
<Pack>True</Pack>
<PackagePath></PackagePath>
</None>
</ItemGroup>
<ItemGroup>
<Compile Remove="Attributes\ComputedAttribute.cs" />
<Compile Remove="Attributes\ExplicitKeyAttribute.cs" />
<Compile Remove="Attributes\IgnoreAttrbute.cs" />
<Compile Remove="Attributes\KeyAttribute.cs" />
<Compile Remove="Attributes\MemoryCacheAttribute.cs" />
<Compile Remove="Attributes\RedisCacheAttribute.cs" />
<Compile Remove="Attributes\TableAttribute.cs" />
<Compile Remove="Attributes\UnitOfWorkIInterceptor.cs" />
<Compile Remove="Attributes\WriteAttribute.cs" />
<Compile Remove="Core\App\AppContext.cs" />
<Compile Remove="Core\App\IAppContext.cs" />
<Compile Remove="Core\App\InternalApp.cs" />
<Compile Remove="Core\Dapper\ISqlDapper.cs" />
<Compile Remove="Core\Dapper\SqlDapper.cs" />
<Compile Remove="Core\DbContextCore\InMemoryDbContext.cs" />
<Compile Remove="Core\DbContextCore\MongoDbContext.cs" />
<Compile Remove="Core\DbContextCore\ShardDbContextFactory.cs" />
<Compile Remove="Core\IDbContext\IInMemoryDbContext.cs" />
<Compile Remove="Core\IDbContext\IMongoDbContext.cs" />
<Compile Remove="Core\Module\MoudleService.cs" />
<Compile Remove="DependencyInjection\AspectCoreContainer.cs" />
<Compile Remove="Extensions\AutoMapperExtension.cs" />
<Compile Remove="Extensions\ComparisonHelper.cs" />
<Compile Remove="Extensions\EnumerableExtensions.cs" />
<Compile Remove="Extensions\GenericExtension.cs" />
<Compile Remove="Extensions\IoCContainerExtensions.cs" />
<Compile Remove="Extensions\MiddlewareExtensions.cs" />
<Compile Remove="Extensions\MvcExtension.cs" />
<Compile Remove="Extensions\ServiceCollectionExtension.cs" />
<Compile Remove="Extensions\SqlBuilder.cs" />
<Compile Remove="Helpers\BoolNullableConverter.cs" />
<Compile Remove="Helpers\CacheKey.cs" />
<Compile Remove="Helpers\HttpHelper.cs" />
<Compile Remove="Helpers\RegistryHelper.cs" />
<Compile Remove="IoC\AspectCoreContainer.cs" />
<Compile Remove="IoC\AutofacModuleRegister.cs" />
<Compile Remove="Mapping\AutoMapperModule.cs" />
<Compile Remove="Mapping\IAutoMapperConfiguration.cs" />
<Compile Remove="Mapping\IMapFromAttributeTypeFinder.cs" />
<Compile Remove="Mapping\IMapper.cs" />
<Compile Remove="Mapping\IMapToAttributeTypeFinder.cs" />
<Compile Remove="Mapping\IMapTuple.cs" />
<Compile Remove="Mapping\MapFromAttribute.cs" />
<Compile Remove="Mapping\MapFromAttributeTypeFinder.cs" />
<Compile Remove="Mapping\MapToAttribute.cs" />
<Compile Remove="Mapping\MapToAttributeTypeFinder.cs" />
<Compile Remove="Mapping\MapTupleProfile.cs" />
<Compile Remove="Options\WeixinOption.cs" />
<Compile Remove="Page\JQueryDataTablePageInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Remove="CodeTemplate\ControllersTemplate.txt" />
<None Remove="CodeTemplate\InputDtoTemplate.txt" />
<None Remove="CodeTemplate\IRepositoryTemplate.txt" />
<None Remove="CodeTemplate\IServiceTemplate.txt" />
<None Remove="CodeTemplate\ModelsTemplate.txt" />
<None Remove="CodeTemplate\OuputDtoTemplate.txt" />
<None Remove="CodeTemplate\ProfileTemplate.txt" />
<None Remove="CodeTemplate\RepositoryTemplate.txt" />
<None Remove="CodeTemplate\ServiceTemplate.txt" />
<None Remove="CodeTemplate\VueJsTemplate.txt" />
<None Remove="CodeTemplate\VueTemplate.txt" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="CodeTemplate\ControllersTemplate.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
<EmbeddedResource Include="CodeTemplate\InputDtoTemplate.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
<EmbeddedResource Include="CodeTemplate\IRepositoryTemplate.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
<EmbeddedResource Include="CodeTemplate\IServiceTemplate.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
<EmbeddedResource Include="CodeTemplate\ModelsTemplate.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
<EmbeddedResource Include="CodeTemplate\OuputDtoTemplate.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
<EmbeddedResource Include="CodeTemplate\ProfileTemplate.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
<EmbeddedResource Include="CodeTemplate\RepositoryTemplate.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
<EmbeddedResource Include="CodeTemplate\ServiceTemplate.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
<EmbeddedResource Include="CodeTemplate\VueJsTemplate.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
<EmbeddedResource Include="CodeTemplate\VueTemplate.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<PackageReference Include="AutoMapper" Version="10.1.1" />
<PackageReference Include="CSRedisCore" Version="3.6.6" />
<PackageReference Include="Dapper" Version="2.0.78" />
<PackageReference Include="Dapper.SqlBuilder" Version="2.0.78" />
<PackageReference Include="Devart.Data.Oracle.EFCore" Version="9.14.1204" />
<PackageReference Include="DotNetCore.NPOI" Version="1.2.3" />
<PackageReference Include="HtmlAgilityPack" Version="1.11.31" />
<PackageReference Include="log4net" Version="2.0.12" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="5.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="5.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.4" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="5.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.1" />
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
<PackageReference Include="MiniProfiler.AspNetCore" Version="4.2.22" />
<PackageReference Include="MiniProfiler.AspNetCore.Mvc" Version="4.2.22" />
<PackageReference Include="MiniProfiler.EntityFrameworkCore" Version="4.2.22" />
<PackageReference Include="MySql.Data" Version="8.0.23" />
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="8.1.1" />
<PackageReference Include="Npgsql" Version="5.0.3" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="5.0.2" />
<PackageReference Include="NPinyin.Core" Version="3.0.0" />
<PackageReference Include="Oracle.ManagedDataAccess.Core" Version="3.21.1" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="5.0.0-alpha.2" />
<PackageReference Include="QRCoder" Version="1.4.1" />
<PackageReference Include="Quartz" Version="3.2.4" />
<PackageReference Include="SgmlReader.NetCore" Version="1.0.0" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.2" />
<PackageReference Include="System.Drawing.Common" Version="5.0.2" />
<PackageReference Include="System.Management" Version="5.0.0" />
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Update="CodeTemplate\ApplicationTemplate.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<Folder Include="Filters\" />
</ItemGroup>
</Project>

49
Znyc.Cloudcar.Admin.Commons/Config/Configs.cs

@ -0,0 +1,49 @@
using Microsoft.Extensions.Configuration;
using Znyc.Cloudcar.Admin.Commons.Core.App;
namespace Znyc.Cloudcar.Admin.Commons
{
/// <summary>
/// 配置文件读取操作
/// </summary>
public class Configs
{
public static IConfiguration configuration;
static Configs()
{
configuration = App.GetService<IConfiguration>();
}
/// <summary>
/// 根据Key获取数配置内容
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static IConfigurationSection GetSection(string key)
{
return configuration.GetSection(key);
}
/// <summary>
/// 根据section和key获取配置内容
/// </summary>
/// <param name="section"></param>
/// <param name="key"></param>
/// <returns></returns>
public static string GetConfigurationValue(string section, string key)
{
return GetSection(section)?[key];
}
/// <summary>
/// 根据Key获取数据库连接字符串
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static string GetConnectionString(string key)
{
return configuration.GetConnectionString(key);
}
}
}

79
Znyc.Cloudcar.Admin.Commons/Const/CommonConst.cs

@ -0,0 +1,79 @@

namespace Znyc.Cloudcar.Admin.Commons
{
/// <summary>
/// 默认常量
/// </summary>
public static class CommonConst
{
/// <summary>
/// 薪资待遇
/// </summary>
public const long Dictionary_Welfare = 1;
/// <summary>
/// 工作经验
/// </summary>
public const long Dictionary_Experience = 2;
/// <summary>
/// 活动
/// </summary>
public const long Dictionary_Activity = 3;
/// <summary>
/// 默认图片地址
/// </summary>
public const string Default_Image_Prefix =
"https://zhongnengyunche.com/cloudcar/wx/upload/avatar/";
/// <summary>
/// 默认头像名称
/// </summary>
public const string Default_AvataUrl = "Default_AvatarUrl.png";
/// <summary>
/// 默认实名图片地址
/// </summary>
public const string Default_Identity_Prefix =
"https://zhongnengyunche.com/authentication/{0}/";
/// <summary>
/// 默认名称
/// </summary>
public const string Default_UserName = "先生";
/// <summary>
/// 默认Banner图片地址
/// </summary>
public const string Default_Banner_Prefix = "https://zhongnengyunche.com/cloudcar/wx/upload/banner/";
/// <summary>
/// 默认意见反馈图片地址
/// </summary>
public const string Default_FeedbackPic_Prefix = "https://zhongnengyunche.com/cloudcar/wx/upload/feedback/";
/// <summary>
/// 默认活动图片地址
/// </summary>
public const string Default_Activity_Prefix = "https://zhongnengyunche.com/cloudcar/wx/upload/activity/";
/// <summary>
/// 充值活动详情-名称
/// </summary>
public const string RechargeIntro_Name = "{0}云币";
/// <summary>
/// 充值活动详情-描述
/// </summary>
public const string RechargeIntro_Description = "{0}云币(可拨打{0}个电话)";
/// <summary>
/// 空字符串
/// </summary>
public const string String_Empty = " ";
}
}

90
Znyc.Cloudcar.Admin.Commons/Const/CurrencyConst.cs

@ -0,0 +1,90 @@
namespace Znyc.Cloudcar.Admin.Commons
{
/// <summary>
/// 系统
/// </summary>
public class SystemConst
{
/// <summary>
/// 当前环境
/// </summary>
public const string ASPNETCORE_ENVIRONMENT = "ASPNETCORE_ENVIRONMENT";
}
/// <summary>
/// 积分常量
/// </summary>
public class CurrencyConst
{
/// <summary>
/// 首次登陆
/// </summary>
public const int FirstLogin = 3;
/// <summary>
/// 邀新用户
/// </summary>
public const int NewUsers = 2;
/// <summary>
/// 每日分享
/// </summary>
public const int DailyShare = 1;
/// <summary>
/// 实名认证
/// </summary>
public const int RealName = 1;
/// <summary>
/// 每日签到
/// </summary>
public const int Signin = 1;
/// <summary>
/// 拔打求职电话
/// </summary>
public const int CallApplyJobPhone = 1;
/// <summary>
/// 拔打招聘电话
/// </summary>
public const int CallCloudcarPhone = 1;
/// <summary>
/// 招聘置顶
/// </summary>
public const int TopCloudcar = 50;
/// <summary>
/// 求职置顶
/// </summary>
public const int TopApplyJob = 50;
/// <summary>
/// 刷新招聘
/// </summary>
public const int RefreshCloudcar = 5;
/// <summary>
/// 刷新求职
/// </summary>
public const int RefreshApplyJob = 1;
}
/// <summary>
/// 积分操作类型常量
/// </summary>
public class CurrencyOperatingTypeConst
{
/// <summary>
/// 增加
/// </summary>
public const string Add = "+";
/// <summary>
/// 减少
/// </summary>
public const string Reduce = "-";
}
}

115
Znyc.Cloudcar.Admin.Commons/Const/ReturnConst.cs

@ -0,0 +1,115 @@
namespace Znyc.Cloudcar.Admin.Commons
{
/// <summary>
/// 返回
/// </summary>
public static class ReturnConst
{
/// <summary>
///
/// </summary>
public const string Password_Error = "密码错误,请重新输入。";
/// <summary>
///
/// </summary>
public const string User_Not_Exist = "系统不存在该用户,请重新确认。";
/// <summary>
///
/// </summary>
public const string User_Disable = "该用户已被禁用,请联系管理员。";
/// <summary>
/// 审批结果-通过
/// </summary>
public const string Approved = "审核通过";
/// <summary>
/// 备注
/// </summary>
public const string Approved_Note = "欢迎点击转发分享";
/// <summary>
/// 审批结果-失败
/// </summary>
public const string Audit_Failed = "审核失败";
/// <summary>
///
/// </summary>
public const string Year = "年";
/// <summary>
///
/// </summary>
public const string Month = "月";
/// <summary>
///
/// </summary>
public const string Day = "日";
/// <summary>
/// 审批类型-求职失败
/// </summary>
public const string Job_Audit_Failed = "发布的求职信息审核失败";
/// <summary>
/// 审批类型-招聘失败
/// </summary>
public const string Cloud_Audit_Failed = "发布的设备信息审核失败";
/// <summary>
/// 审批类型-求职通过
/// </summary>
public const string Cloud_Approved = "您的设备信息审核通过";
/// <summary>
/// 审批类型-招聘通过
/// </summary>
public const string Recruit_Approved = "您的招聘信息审核通过";
/// <summary>
/// 审批类型-实名认证通过
/// </summary>
public const string RealName_Approved = "您的实名认证信息认证成功";
/// <summary>
/// 审批类型-实名认证失败
/// </summary>
public const string RealName_Audit_Failed = "您的实名认证信息认证失败";
/// <summary>
/// 结束时间必须大于开始时间
/// </summary>
public const string Time_Error = "结束时间必须大于开始时间!";
/// <summary>
/// 结束时间必须大于当前时间
/// </summary>
public const string EndTime_Error = "结束时间必须大于当前时间!";
/// <summary>
/// 时间重叠
/// </summary>
public const string Time_Overlap = "请检查开始日期时间和结束日期时间!存在重叠时间!";
/// <summary>
/// 信息不存在
/// </summary>
public const string Not_Exist = "该信息不存在!";
/// <summary>
/// 活动类型进行中
/// </summary>
public const string Activity_Ongoing = "该活动类型正在进行中";
/// <summary>
/// 字典分类编码不能重复
/// </summary>
public const string Dictionary_Code_Exist = "字典分类编码不能重复";
}
}

289
Znyc.Cloudcar.Admin.Commons/Core/App/App.cs

@ -0,0 +1,289 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
namespace Znyc.Cloudcar.Admin.Commons.Core.App
{
/// <summary>
/// 全局应用类
/// </summary>
public static class App
{
/// <summary>
/// 全局配置选项
/// </summary>
public static IConfiguration Configuration;
/// <summary>
/// 应用服务
/// </summary>
public static IServiceCollection Services;
/// <summary>
/// 全局配置构建器
/// </summary>
private static IConfigurationBuilder ConfigurationBuilder;
/// <summary>
/// 私有环境变量,避免重复解析
/// </summary>
private static IWebHostEnvironment _webHostEnvironment;
/// <summary>
/// 应用有效程序集
/// </summary>
public static readonly IEnumerable<Assembly> Assemblies;
/// <summary>
/// 有效程序集类型
/// </summary>
public static readonly IEnumerable<Type> EffectiveTypes;
/// <summary>
/// 构造函数
/// </summary>
static App()
{
// 编译配置
// Configuration =ConfigurationBuilder.Build();
}
/// <summary>
/// 应用环境,如,是否是开发环境,生产环境等
/// </summary>
public static IWebHostEnvironment WebHostEnvironment =>
_webHostEnvironment ??= GetService<IWebHostEnvironment>();
/// <summary>
/// 服务提供器
/// </summary>
public static IServiceProvider ServiceProvider =>
HttpContext?.RequestServices ?? Services.BuildServiceProvider();
/// <summary>
/// 获取请求上下文
/// </summary>
public static HttpContext HttpContext => HttpContextLocal.Current();
/// <summary>
/// 获取请求生命周期的服务
/// </summary>
/// <typeparam name="TService"></typeparam>
/// <returns></returns>
public static TService GetService<TService>()
where TService : class
{
return GetService(typeof(TService)) as TService;
}
/// <summary>
/// 获取请求生命周期的服务
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public static object GetService(Type type)
{
return ServiceProvider.GetService(type);
}
/// <summary>
/// 获取请求生命周期的服务
/// </summary>
/// <typeparam name="TService"></typeparam>
/// <returns></returns>
public static TService GetRequiredService<TService>()
where TService : class
{
return GetRequiredService(typeof(TService)) as TService;
}
/// <summary>
/// 获取请求生命周期的服务
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public static object GetRequiredService(Type type)
{
return ServiceProvider.GetRequiredService(type);
}
/// <summary>
/// 获取选项
/// </summary>
/// <typeparam name="TOptions">强类型选项类</typeparam>
/// <returns>TOptions</returns>
public static TOptions GetOptions<TOptions>()
where TOptions : class, new()
{
return GetService<IOptions<TOptions>>()?.Value;
}
/// <summary>
/// 获取选项
/// </summary>
/// <typeparam name="TOptions">强类型选项类</typeparam>
/// <returns>TOptions</returns>
public static TOptions GetOptionsMonitor<TOptions>()
where TOptions : class, new()
{
return GetService<IOptionsMonitor<TOptions>>()?.CurrentValue;
}
/// <summary>
/// 获取选项
/// </summary>
/// <typeparam name="TOptions">强类型选项类</typeparam>
/// <returns>TOptions</returns>
public static TOptions GetOptionsSnapshot<TOptions>()
where TOptions : class, new()
{
return GetService<IOptionsSnapshot<TOptions>>()?.Value;
}
#region
/// <summary>
/// 添加配置文件
/// </summary>
/// <param name="config"></param>
/// <param name="env"></param>
internal static void AddConfigureFiles(IConfigurationBuilder config, IHostEnvironment env)
{
// 读取忽略的配置文件
string[] ignoreConfigurationFiles = config.Build()
.GetSection("IgnoreConfigurationFiles").Get<string[]>()
?? Array.Empty<string>();
// 加载配置
AutoAddJsonFiles(config, env, ignoreConfigurationFiles);
AutoAddXmlFiles(config, env, ignoreConfigurationFiles);
// 存储配置
ConfigurationBuilder = config;
}
/// <summary>
/// 自动加载自定义 .json 配置文件
/// </summary>
/// <param name="config"></param>
/// <param name="env"></param>
/// <param name="ignoreConfigurationFiles"></param>
public static void AutoAddJsonFiles(IConfigurationBuilder config, IHostEnvironment env,
string[] ignoreConfigurationFiles)
{
// 获取程序目录下的所有配置文件
IEnumerable<string> jsonFiles = Directory.GetFiles(AppContext.BaseDirectory, "*.json", SearchOption.TopDirectoryOnly)
.Union(
Directory.GetFiles(Directory.GetCurrentDirectory(), "*.json", SearchOption.TopDirectoryOnly)
)
.Where(u => !excludeJsons.Contains(Path.GetFileName(u)) &&
!ignoreConfigurationFiles.Contains(Path.GetFileName(u)) &&
!runtimeJsonSuffixs.Any(j => u.EndsWith(j)));
if (!jsonFiles.Any())
{
return;
}
// 获取环境变量名
string envName = env.EnvironmentName;
List<string> envFiles = new List<string>();
// 自动加载配置文件
foreach (string jsonFile in jsonFiles)
{
// 处理带环境的配置文件
if (Path.GetFileNameWithoutExtension(jsonFile).EndsWith($".{envName}"))
{
envFiles.Add(jsonFile);
continue;
}
config.AddJsonFile(jsonFile, true, true);
}
// 配置带环境的配置文件
envFiles.ForEach(u => config.AddJsonFile(u, true, true));
}
/// <summary>
/// 自动加载自定义 .xml 配置文件
/// </summary>
/// <param name="config"></param>
/// <param name="env"></param>
/// <param name="ignoreConfigurationFiles"></param>
public static void AutoAddXmlFiles(IConfigurationBuilder config, IHostEnvironment env,
string[] ignoreConfigurationFiles)
{
// 获取程序目录下的所有配置文件,必须以 .config.xml 结尾
IEnumerable<string> xmlFiles = Directory.GetFiles(AppContext.BaseDirectory, "*.xml", SearchOption.TopDirectoryOnly)
.Union(
Directory.GetFiles(Directory.GetCurrentDirectory(), "*.xml", SearchOption.TopDirectoryOnly)
)
.Where(u => !ignoreConfigurationFiles.Contains(Path.GetFileName(u)) &&
u.EndsWith(".config.xml", StringComparison.OrdinalIgnoreCase));
if (!xmlFiles.Any())
{
return;
}
// 获取环境变量名
string envName = env.EnvironmentName;
List<string> envFiles = new List<string>();
// 自动加载配置文件
foreach (string xmlFile in xmlFiles)
{
// 处理带环境的配置文件
if (Path.GetFileNameWithoutExtension(xmlFile).EndsWith($".{envName}.config"))
{
envFiles.Add(xmlFile);
continue;
}
config.AddXmlFile(xmlFile, true, true);
}
// 配置带环境的配置文件
envFiles.ForEach(u => config.AddXmlFile(u, true, true));
}
/// <summary>
/// 默认排除配置项
/// </summary>
private static readonly string[] excludeJsons =
{
"appsettings.json",
"appsettings.Development.json",
"appsettings.Production.json",
"bundleconfig.json",
"bundleconfig.Development.json",
"bundleconfig.Production.json",
"compilerconfig.json",
"compilerconfig.Development.json",
"compilerconfig.Production.json"
};
/// <summary>
/// 排除运行时 Json 后缀
/// </summary>
private static readonly string[] runtimeJsonSuffixs =
{
"deps.json",
"runtimeconfig.dev.json",
"runtimeconfig.prod.json",
"runtimeconfig.json"
};
#endregion
}
}

32
Znyc.Cloudcar.Admin.Commons/Core/App/HostingStartup.cs

@ -0,0 +1,32 @@
using Microsoft.AspNetCore.Hosting;
using Znyc.Cloudcar.Admin.Commons.Core.App;
//通过HostingStartup指定要启动的类型
[assembly: HostingStartup(typeof(HostingStartup))]
namespace Znyc.Cloudcar.Admin.Commons.Core.App
{
/// <summary>
/// 配置程序启动时自动注入
/// </summary>
public sealed class HostingStartup : IHostingStartup
{
/// <summary>
/// 配置应用启动
/// </summary>
/// <param name="builder"></param>
public void Configure(IWebHostBuilder builder)
{
//可以添加配置
builder.ConfigureAppConfiguration((hostingContext, config) =>
{
// 自动装载配置
App.AddConfigureFiles(config, hostingContext.HostingEnvironment);
});
//可以添加ConfigureServices
// 自动注入 AddApp() 服务
builder.ConfigureServices(services => { });
}
}
}

69
Znyc.Cloudcar.Admin.Commons/Core/App/HttpContextLocal.cs

@ -0,0 +1,69 @@
using Microsoft.AspNetCore.Http;
using System;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading;
namespace Znyc.Cloudcar.Admin.Commons.Core.App
{
/// <summary>
/// 获取 HttpContext 上下文
/// </summary>
public static class HttpContextLocal
{
private static Func<object> _asyncLocalAccessor;
private static Func<object, object> _holderAccessor;
private static Func<object, HttpContext> _httpContextAccessor;
/// <summary>
/// 获取当前 HttpContext 对象
/// </summary>
/// <returns></returns>
public static HttpContext Current()
{
object asyncLocal = (_asyncLocalAccessor ??= CreateAsyncLocalAccessor())();
if (asyncLocal == null)
{
return null;
}
object holder = (_holderAccessor ??= CreateHolderAccessor(asyncLocal))(asyncLocal);
if (holder == null)
{
return null;
}
return (_httpContextAccessor ??= CreateHttpContextAccessor(holder))(holder);
// 创建异步本地访问器
static Func<object> CreateAsyncLocalAccessor()
{
FieldInfo fieldInfo = typeof(HttpContextAccessor).GetField("_httpContextCurrent",
BindingFlags.Static | BindingFlags.NonPublic);
MemberExpression field = Expression.Field(null, fieldInfo);
return Expression.Lambda<Func<object>>(field).Compile();
}
// 创建常驻 HttpContext 访问器
static Func<object, object> CreateHolderAccessor(object asyncLocal)
{
Type holderType = asyncLocal.GetType().GetGenericArguments()[0];
MethodInfo method = typeof(AsyncLocal<>).MakeGenericType(holderType).GetProperty("Value").GetGetMethod();
ParameterExpression target = Expression.Parameter(typeof(object));
UnaryExpression convert = Expression.Convert(target, asyncLocal.GetType());
MethodCallExpression getValue = Expression.Call(convert, method);
return Expression.Lambda<Func<object, object>>(getValue, target).Compile();
}
// 获取 HttpContext 访问器
static Func<object, HttpContext> CreateHttpContextAccessor(object holder)
{
ParameterExpression target = Expression.Parameter(typeof(object));
UnaryExpression convert = Expression.Convert(target, holder.GetType());
MemberExpression field = Expression.Field(convert, "Context");
UnaryExpression convertAsResult = Expression.Convert(field, typeof(HttpContext));
return Expression.Lambda<Func<object, HttpContext>>(convertAsResult, target).Compile();
}
}
}
}

461
Znyc.Cloudcar.Admin.Commons/Core/Application/BaseApp.cs

@ -0,0 +1,461 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Znyc.Cloudcar.Admin.Commons.Entitys;
using Znyc.Cloudcar.Admin.Commons.IServices;
using Znyc.Cloudcar.Admin.Commons.Pages;
namespace Znyc.Cloudcar.Admin.Commons.Application
{
/// <summary>
/// 业务层基类,Service用于普通的数据库操作
/// </summary>
/// <typeparam name="T">实体类型</typeparam>
/// <typeparam name="TDto">实体类型</typeparam>
/// <typeparam name="TService">Service类型</typeparam>
/// <typeparam name="Tkey">主键类型</typeparam>
public class BaseApp<T, TDto, TService, Tkey>
where T : Entity
where TDto : class
where TService : IService<T, TDto, Tkey>
{
/// <summary>
/// 用于普通的数据库操作
/// </summary>
/// <value>The service.</value>
protected IService<T, TDto, Tkey> service;
/// <summary>
/// </summary>
/// <param name="_service"></param>
public BaseApp(IService<T, TDto, Tkey> _service)
{
service = _service;
}
/// <summary>
/// 同步物理删除实体。
/// </summary>
/// <param name="entity">实体</param>
/// <returns></returns>
public virtual bool Delete(T entity)
{
return service.Delete(entity);
}
/// <summary>
/// 同步物理删除实体。
/// </summary>
/// <param name="id">主键</param>
/// <returns></returns>
public virtual bool Delete(Tkey id)
{
return service.Delete(id);
}
/// <summary>
/// 异步物理删除实体。
/// </summary>
/// <param name="id">主键</param>
/// <returns></returns>
public virtual Task<bool> DeleteAsync(Tkey id)
{
return service.DeleteAsync(id);
}
/// <summary>
/// 异步物理删除实体。
/// </summary>
/// <param name="entity">实体</param>
/// <returns></returns>
public virtual Task<bool> DeleteAsync(T entity)
{
return service.DeleteAsync(entity);
}
/// <summary>
/// 按主键批量删除
/// </summary>
/// <param name="ids"></param>
/// <returns></returns>
public virtual bool DeleteBatch(IList<dynamic> ids)
{
return service.DeleteBatch(ids);
}
/// <summary>
/// 按条件批量删除
/// </summary>
/// <param name="where">条件</param>
/// <returns></returns>
public virtual bool DeleteBatchWhere(string where)
{
return service.DeleteBatchWhere(where);
}
/// <summary>
/// 软删除信息,将IsDeleted设置为1-删除,0-恢复删除
/// </summary>
/// <param name="bl">true为不删除,false删除</param>
/// <param name="id">主键ID</param>
/// <param name="userId">操作用户</param>
/// <returns></returns>
public virtual bool DeleteSoft(bool bl, Tkey id, int userId)
{
return service.DeleteSoft(bl, id, userId);
}
/// <summary>
/// 异步软删除信息,将IsDeleted设置为1-删除,0-恢复删除
/// </summary>
/// <param name="bl">true为不删除,false删除</param>
/// <param name="id">主键ID</param>
/// <param name="userId">操作用户</param>
/// <returns></returns>
public virtual Task<bool> DeleteSoftAsync(bool bl, Tkey id, int userId)
{
return service.DeleteSoftAsync(bl, id, userId);
}
/// <summary>
/// 同步查询单个实体。
/// </summary>
/// <param name="id">主键</param>
/// <returns></returns>
public virtual T Get(Tkey id)
{
return service.Get(id);
}
/// <summary>
/// 同步查询单个实体。
/// </summary>
/// <param name="where">查询条件</param>
/// <returns></returns>
public virtual T GetWhere(string where)
{
return service.GetWhere(where);
}
/// <summary>
/// 异步查询单个实体。
/// </summary>
/// <param name="where">查询条件</param>
/// <returns></returns>
public virtual async Task<T> GetWhereAsync(string where)
{
return await service.GetWhereAsync(where);
}
/// <summary>
/// 根据查询条件查询前多少条数据
/// </summary>
/// <param name="top">多少条数据</param>
/// <param name="where">查询条件</param>
/// <returns></returns>
public virtual IEnumerable<T> GetListTopWhere(int top, string where = null)
{
return service.GetListTopWhere(top, where);
}
/// <summary>
/// 同步查询所有实体。
/// </summary>
/// <returns></returns>
public virtual IEnumerable<T> GetAll()
{
return service.GetAll();
}
/// <summary>
/// 异步步查询所有实体。
/// </summary>
/// <returns></returns>
public virtual Task<IEnumerable<T>> GetAllAsync()
{
return service.GetAllAsync();
}
/// <summary>
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public virtual Task<T> GetAsync(Tkey id)
{
return service.GetAsync(id);
}
/// <summary>
/// 根据查询条件查询数据
/// </summary>
/// <param name="where">查询条件</param>
/// <returns></returns>
public virtual IEnumerable<T> GetListWhere(string where = null)
{
return service.GetListWhere(where);
}
/// <summary>
/// 异步根据查询条件查询数据
/// </summary>
/// <param name="where">查询条件</param>
/// <returns></returns>
public virtual async Task<IEnumerable<T>> GetListWhereAsync(string where = null)
{
return await service.GetListWhereAsync(where);
}
/// <summary>
/// 同步新增实体。
/// </summary>
/// <param name="entity">实体</param>
/// <returns></returns>
public virtual long Insert(T entity)
{
return service.Insert(entity);
}
/// <summary>
/// 异步步新增实体。
/// </summary>
/// <param name="entity">实体</param>
/// <returns></returns>
public virtual Task<int> InsertAsync(T entity)
{
return service.InsertAsync(entity);
}
/// <summary>
/// 同步更新实体。
/// </summary>
/// <param name="entity">实体</param>
/// <param name="id">主键ID</param>
/// <returns></returns>
public virtual bool Update(T entity, Tkey id)
{
return service.Update(entity, id);
}
/// <summary>
/// 异步更新实体。
/// </summary>
/// <param name="entity">实体</param>
/// <param name="id">主键ID</param>
/// <returns></returns>
public virtual Task<bool> UpdateAsync(T entity, Tkey id)
{
return service.UpdateAsync(entity, id);
}
/// <summary>
/// 更新某一字段值
/// </summary>
/// <param name="strField">字段</param>
/// <param name="fieldValue">字段值</param>
/// <param name="where">条件,为空更新所有内容</param>
/// <returns></returns>
public virtual bool UpdateTableField(string strField, string fieldValue, string where)
{
return service.UpdateTableField(strField, fieldValue, where);
}
/// <summary>
/// 查询软删除的数据,如果查询条件为空,即查询所有软删除的数据
/// </summary>
/// <param name="where">查询条件</param>
/// <returns></returns>
public virtual IEnumerable<T> GetAllByIsIsDeleted(string where = null)
{
return service.GetAllByIsIsDeleted(where);
}
/// <summary>
/// 查询未软删除的数据,如果查询条件为空,即查询所有未软删除的数据
/// </summary>
/// <param name="where">查询条件</param>
/// <returns></returns>
public virtual IEnumerable<T> GetAllByIsNotIsDeleted(string where = null)
{
return service.GetAllByIsNotIsDeleted(where);
}
/// <summary>
/// 查询有效的数据,如果查询条件为空,即查询所有有效的数据
/// </summary>
/// <param name="where">查询条件</param>
/// <returns></returns>
public virtual IEnumerable<T> GetAllByIsEnabledMark(string where = null)
{
return service.GetAllByIsEnabledMark(where);
}
/// <summary>
/// 查询无效的数据,如果查询条件为空,即查询所有无效的数据
/// </summary>
/// <param name="where">查询条件</param>
/// <returns></returns>
public virtual IEnumerable<T> GetAllByIsNotEnabledMark(string where = null)
{
return service.GetAllByIsNotEnabledMark(where);
}
/// <summary>
/// 查询未软删除且有效的数据,如果查询条件为空,即查询所有数据
/// </summary>
/// <param name="where">查询条件</param>
/// <returns></returns>
public virtual IEnumerable<T> GetAllByIsNotDeleteAndEnabledMark(string where = null)
{
return service.GetAllByIsNotDeleteAndEnabledMark(where);
}
/// <summary>
/// 查询软删除的数据,如果查询条件为空,即查询所有软删除的数据
/// </summary>
/// <param name="where">查询条件</param>
/// <returns></returns>
public virtual async Task<IEnumerable<T>> GetAllByIsIsDeletedAsync(string where = null)
{
return await service.GetAllByIsIsDeletedAsync(where);
}
/// <summary>
/// 查询未软删除的数据,如果查询条件为空,即查询所有未软删除的数据
/// </summary>
/// <param name="where">查询条件</param>
/// <returns></returns>
public virtual async Task<IEnumerable<T>> GetAllByIsNotIsDeletedAsync(string where = null)
{
return await service.GetAllByIsNotIsDeletedAsync(where);
}
/// <summary>
/// 查询有效的数据,如果查询条件为空,即查询所有有效的数据
/// </summary>
/// <param name="where">查询条件</param>
/// <returns></returns>
public virtual async Task<IEnumerable<T>> GetAllByIsEnabledMarkAsync(string where = null)
{
return await service.GetAllByIsEnabledMarkAsync(where);
}
/// <summary>
/// 查询无效的数据,如果查询条件为空,即查询所有无效的数据
/// </summary>
/// <param name="where">查询条件</param>
/// <returns></returns>
public virtual async Task<IEnumerable<T>> GetAllByIsNotEnabledMarkAsync(string where = null)
{
return await service.GetAllByIsNotEnabledMarkAsync(where);
}
/// <summary>
/// 查询未软删除且有效的数据,如果查询条件为空,即查询所有数据
/// </summary>
/// <param name="where">查询条件</param>
/// <returns></returns>
public virtual async Task<IEnumerable<T>> GetAllByIsNotDeleteAndEnabledMarkAsync(string where = null)
{
return await service.GetAllByIsNotDeleteAndEnabledMarkAsync(where);
}
/// <summary>
/// 设置数据有效性,将IsEnabled设置为1:有效,0-为无效
/// </summary>
/// <param name="bl">true为有效,false无效</param>
/// <param name="id">主键ID</param>
/// <param name="userId">操作用户</param>
/// <returns></returns>
public virtual bool SetEnabledMark(bool bl, Tkey id, int userId = 0)
{
return service.SetEnabledMark(bl, id, userId);
}
/// <summary>
/// 异步设置数据有效性,将IsEnabled设置为1:有效,0-为无效
/// </summary>
/// <param name="bl">true为有效,false无效</param>
/// <param name="id">主键ID</param>
/// <param name="userId">操作用户</param>
/// <returns></returns>
public virtual async Task<bool> SetEnabledMarkAsync(bool bl, Tkey id, int userId = 0)
{
return await service.SetEnabledMarkAsync(bl, id, userId);
}
/// <summary>
/// 根据条件查询数据库,并返回对象集合(用于分页数据显示)
/// </summary>
/// <param name="condition">查询的条件</param>
/// <param name="info">分页实体</param>
/// <returns>指定对象的集合</returns>
public virtual List<T> FindWithPager(string condition, PagerInfo info)
{
return service.FindWithPager(condition, info);
}
/// <summary>
/// 根据条件查询数据库,并返回对象集合(用于分页数据显示)
/// </summary>
/// <param name="condition">查询的条件</param>
/// <param name="info">分页实体</param>
/// <param name="fieldToSort">排序字段</param>
/// <returns>指定对象的集合</returns>
public virtual List<T> FindWithPager(string condition, PagerInfo info, string fieldToSort)
{
return service.FindWithPager(condition, info, fieldToSort);
}
/// <summary>
/// 根据条件查询数据库,并返回对象集合(用于分页数据显示)
/// </summary>
/// <param name="condition">查询的条件</param>
/// <param name="info">分页实体</param>
/// <param name="fieldToSort">排序字段</param>
/// <param name="desc">是否降序</param>
/// <returns>指定对象的集合</returns>
public virtual List<T> FindWithPager(string condition, PagerInfo info, string fieldToSort, bool desc)
{
return service.FindWithPager(condition, info, fieldToSort, desc);
}
/// <summary>
/// 分页查询,自行封装sql语句
/// </summary>
/// <param name="condition">查询条件</param>
/// <param name="info">分页信息</param>
/// <param name="fieldToSort">排序字段</param>
/// <param name="desc">排序方式 true为desc,false为asc</param>
/// <returns></returns>
public virtual List<T> FindWithPagerSql(string condition, PagerInfo info, string fieldToSort, bool desc)
{
return service.FindWithPagerSql(condition, info, fieldToSort, desc);
}
/// <summary>
/// 分页查询包含用户信息
/// 查询主表别名为t1,用户表别名为t2,在查询字段需要注意使用t1.xxx格式,xx表示主表字段
/// 用户信息主要有用户账号:Account、昵称:UserName、真实姓名:RealName、头像:HeadIcon、手机号:MobilePhone
/// 输出对象请在Dtos中进行自行封装,不能是使用实体Model类
/// </summary>
/// <param name="condition">查询条件字段需要加表别名</param>
/// <param name="info">分页信息</param>
/// <param name="fieldToSort">排序字段,也需要加表别名</param>
/// <param name="desc">排序方式</param>
/// <returns></returns>
public virtual List<object> FindWithPagerRelationUser(string condition, PagerInfo info, string fieldToSort,
bool desc)
{
return service.FindWithPagerRelationUser(condition, info, fieldToSort, desc);
}
/// <summary>
/// 根据条件统计数据
/// </summary>
/// <param name="condition">查询条件</param>
/// <returns></returns>
public virtual int GetCountByWhere(string condition)
{
return service.GetCountByWhere(condition);
}
}
}

128
Znyc.Cloudcar.Admin.Commons/Core/Dapper/DapperDbContext.cs

@ -0,0 +1,128 @@
using System.Data;
using Znyc.Cloudcar.Admin.Commons.Core.DataManager;
namespace Znyc.Cloudcar.Admin.Commons.Core.Dapper
{
/// <summary>
/// 注册的时候 InstancePerLifetimeScope
/// 线程内唯一(也就是单个请求内唯一)
/// </summary>
public class DapperDbContext
{
private IDbConnection dbConnection { get; set; }
/// <summary>
/// 事务
/// </summary>
public IDbTransaction DbTransaction { get; set; }
/// <summary>
/// 是否已被提交
/// </summary>
public bool Committed { get; private set; } = true;
/// <summary>
/// 获取的数据库连接
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="masterDb"></param>
/// <returns></returns>
public IDbConnection GetConnection<T>(bool masterDb = true) where T : class
{
if (dbConnection == null || dbConnection.State == ConnectionState.Closed)
{
dbConnection = DBServerProvider.GetDBConnection<T>(masterDb);
}
//if (MiniProfiler.Current != null)
//{
// dbConnection = new StackExchange.Profiling.Data.ProfiledDbConnection((DbConnection)dbConnection, MiniProfiler.Current);
//}
return dbConnection;
}
/// <summary>
/// 开启事务
/// </summary>
public void BeginTransaction()
{
Committed = false;
bool isClosed = dbConnection.State == ConnectionState.Closed;
if (isClosed)
{
dbConnection.Open();
}
DbTransaction = dbConnection?.BeginTransaction();
}
/// <summary>
/// 事务提交
/// </summary>
public void CommitTransaction()
{
DbTransaction?.Commit();
Committed = true;
Dispose();
}
/// <summary>
/// 事务回滚
/// </summary>
public void RollBackTransaction()
{
DbTransaction?.Rollback();
Committed = true;
Dispose();
}
#region Dispose实现
private bool disposedValue; // 要检测冗余调用
/// <summary>
/// 释放
/// </summary>
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
// TODO: 释放托管状态(托管对象)。
}
// TODO: 释放未托管的资源(未托管的对象)并在以下内容中替代终结器。
// TODO: 将大型字段设置为 null。
disposedValue = true;
}
if (dbConnection != null)
{
DbTransaction.Dispose();
dbConnection.Dispose();
}
}
/// <summary>
/// 仅当以上 Dispose(bool disposing) 拥有用于释放未托管资源的代码时才替代终结器。
/// </summary>
public void Dispose()
{
// 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
Dispose(true);
DbTransaction?.Dispose();
if (dbConnection.State == ConnectionState.Open)
{
dbConnection?.Close();
}
// TODO: 如果在以上内容中替代了终结器,则取消注释以下行。
// GC.SuppressFinalize(this);
}
#endregion Dispose实现
}
}

24
Znyc.Cloudcar.Admin.Commons/Core/DataManager/AppDBContextAttribute.cs

@ -0,0 +1,24 @@
using System;
namespace Znyc.Cloudcar.Admin.Commons.Core.DataManager
{
/// <summary>
/// 数据库连接配置特性
/// </summary>
public class AppDBContextAttribute : Attribute
{
/// <summary>
/// 构造函数
/// </summary>
/// <param name="dbConfigName"></param>
public AppDBContextAttribute(string dbConfigName)
{
DbConfigName = dbConfigName;
}
/// <summary>
/// 数据库配置名称
/// </summary>
public string DbConfigName { get; set; }
}
}

230
Znyc.Cloudcar.Admin.Commons/Core/DataManager/DBServerProvider.cs

@ -0,0 +1,230 @@
using Microsoft.Data.Sqlite;
using Microsoft.Extensions.Configuration;
using MySql.Data.MySqlClient;
using Npgsql;
using Oracle.ManagedDataAccess.Client;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Reflection;
using Znyc.Cloudcar.Admin.Commons.Encrypt;
using Znyc.Cloudcar.Admin.Commons.Enums;
using Znyc.Cloudcar.Admin.Commons.Extensions;
namespace Znyc.Cloudcar.Admin.Commons.Core.DataManager
{
/// <summary>
/// 数据库服务提供者
/// </summary>
public class DBServerProvider
{
/// <summary>
/// 数据库配置名称
/// </summary>
private static string dbConfigName = "";
/// <summary>
/// 数据库连接
/// </summary>
private static IDbConnection dbConnection;
#region Dapper Context
/// <summary>
/// 获取默认数据库连接
/// </summary>
/// <returns></returns>
public static string GetConnectionString()
{
return GetConnectionString(dbConfigName);
}
/// <summary>
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static string GetConnectionString(string key)
{
return dbConfigName = key ?? dbConfigName;
}
/// <summary>
/// 获取数据库连接
/// </summary>
/// <param name="masterDb">是否访问主库,默认为是,否则访问从库即只读数据库</param>
/// <returns></returns>
public static IDbConnection GetDBConnection<TEntity>(bool masterDb = true)
{
DbConnectionOptions connectionOptions = GeDbConnectionOptions<TEntity>(masterDb);
string defaultSqlConnectionString = connectionOptions.ConnectionString;
DatabaseType dbType = connectionOptions.DatabaseType;
if (dbType == DatabaseType.SqlServer)
{
dbConnection = new SqlConnection(defaultSqlConnectionString);
}
else if (dbType == DatabaseType.MySql)
{
dbConnection = new MySqlConnection(defaultSqlConnectionString);
}
else if (dbType == DatabaseType.Oracle)
{
dbConnection = new OracleConnection(defaultSqlConnectionString);
}
else if (dbType == DatabaseType.SQLite)
{
dbConnection = new SqliteConnection(defaultSqlConnectionString);
}
else if (dbType == DatabaseType.Npgsql)
{
dbConnection = new NpgsqlConnection(defaultSqlConnectionString);
}
else
{
throw new NotSupportedException("The database is not supported");
}
return dbConnection;
}
/// <summary>
/// 获取数据库连接
/// </summary>
/// <param name="masterDb">是否访问主库,默认为是,否则访问从库即只读数据库</param>
/// <returns></returns>
public static IDbConnection GetDBConnection(bool masterDb = true)
{
DbConnectionOptions connectionOptions = GeDbConnectionOptions(masterDb);
string defaultSqlConnectionString = connectionOptions.ConnectionString;
DatabaseType dbType = connectionOptions.DatabaseType;
if (dbType == DatabaseType.SqlServer)
{
dbConnection = new SqlConnection(defaultSqlConnectionString);
}
else if (dbType == DatabaseType.MySql)
{
dbConnection = new MySqlConnection(defaultSqlConnectionString);
}
else if (dbType == DatabaseType.Oracle)
{
dbConnection = new OracleConnection(defaultSqlConnectionString);
}
else if (dbType == DatabaseType.SQLite)
{
dbConnection = new SqliteConnection(defaultSqlConnectionString);
}
else if (dbType == DatabaseType.Npgsql)
{
dbConnection = new NpgsqlConnection(defaultSqlConnectionString);
}
else
{
throw new NotSupportedException("The database is not supported");
}
return dbConnection;
}
/// <summary>
/// 获取数据库连接连接配置
/// </summary>
/// <typeparam name="TEntity">数据实体</typeparam>
/// <param name="masterDb">是否访问主库,默认为是,否则访问从库即只读数据库</param>
/// <returns></returns>
public static DbConnectionOptions GeDbConnectionOptions<TEntity>(bool masterDb = true)
{
dbConfigName = typeof(TEntity).GetCustomAttribute<AppDBContextAttribute>(false)?.DbConfigName ??
dbConfigName;
bool conStringEncrypt = Configs.GetConfigurationValue("AppSetting", "ConStringEncrypt").ToBool();
if (string.IsNullOrEmpty(dbConfigName))
{
dbConfigName = Configs.GetConfigurationValue("AppSetting", "DefaultDataBase");
}
Dictionary<string, DbConnectionOptions> dictRead = Configs.GetSection("DbConnections:" + dbConfigName + ":ReadDb")
.Get<Dictionary<string, DbConnectionOptions>>();
DbConnectionOptions dbConnectionOptions = new DbConnectionOptions();
bool isDBReadWriteSeparate = Configs.GetConfigurationValue("AppSetting", "IsDBReadWriteSeparate").ToBool();
if (masterDb || !isDBReadWriteSeparate)
{
dbConnectionOptions.ConnectionString =
Configs.GetConfigurationValue("DbConnections:" + dbConfigName + ":MasterDB", "ConnectionString");
dbConnectionOptions.DatabaseType = (DatabaseType)Enum.Parse(typeof(DatabaseType),
Configs.GetConfigurationValue("DbConnections:" + dbConfigName + ":MasterDB", "DatabaseType"));
}
else
{
dbConnectionOptions = GetReadConn(dictRead);
}
if (conStringEncrypt)
{
dbConnectionOptions.ConnectionString = DEncrypt.Decrypt(dbConnectionOptions.ConnectionString);
}
return dbConnectionOptions;
}
/// <summary>
/// 获取数据库连接连接配置
/// </summary>
/// <param name="masterDb">是否访问主库,默认为是,否则访问从库即只读数据库</param>
/// <returns></returns>
public static DbConnectionOptions GeDbConnectionOptions(bool masterDb = true)
{
bool conStringEncrypt = Configs.GetConfigurationValue("AppSetting", "ConStringEncrypt").ToBool();
if (string.IsNullOrEmpty(dbConfigName))
{
dbConfigName = Configs.GetConfigurationValue("AppSetting", "DefaultDataBase");
}
Dictionary<string, DbConnectionOptions> dictRead = Configs.GetSection("DbConnections:" + dbConfigName + ":ReadDb")
.Get<Dictionary<string, DbConnectionOptions>>();
DbConnectionOptions dbConnectionOptions = new DbConnectionOptions();
bool isDBReadWriteSeparate = Configs.GetConfigurationValue("AppSetting", "IsDBReadWriteSeparate").ToBool();
if (masterDb || !isDBReadWriteSeparate)
{
dbConnectionOptions.ConnectionString =
Configs.GetConfigurationValue("DbConnections:" + dbConfigName + ":MasterDB", "ConnectionString");
dbConnectionOptions.DatabaseType = (DatabaseType)Enum.Parse(typeof(DatabaseType),
Configs.GetConfigurationValue("DbConnections:" + dbConfigName + ":MasterDB", "DatabaseType"));
}
else
{
dbConnectionOptions = GetReadConn(dictRead);
}
if (conStringEncrypt)
{
dbConnectionOptions.ConnectionString = DEncrypt.Decrypt(dbConnectionOptions.ConnectionString);
}
return dbConnectionOptions;
}
/// <summary>
/// 按从库数据库连接的策略进行返回连接对象,实现从库的负载均衡
/// </summary>
/// <param name="slaveData"></param>
/// <returns></returns>
private static DbConnectionOptions GetReadConn(Dictionary<string, DbConnectionOptions> slaveData)
{
DbConnectionOptions connectionOptions = new DbConnectionOptions();
string queryDBStrategy = Configs.GetConfigurationValue("AppSetting", "QueryDBStrategy");
if (queryDBStrategy == "Random") //随机策略
{
int index = new Random().Next(0, slaveData.Count - 1);
connectionOptions = slaveData[index.ToString()];
}
else if (queryDBStrategy == "Polling") //轮询策略
{
}
return connectionOptions;
}
#endregion Dapper Context
}
}

42
Znyc.Cloudcar.Admin.Commons/Core/DataManager/DbConnectionOptions.cs

@ -0,0 +1,42 @@
using System.Collections.Generic;
using Znyc.Cloudcar.Admin.Commons.Enums;
namespace Znyc.Cloudcar.Admin.Commons.Core.DataManager
{
/// <summary>
/// 定义主数据和从数据库配置选项
/// </summary>
public class DbConnections
{
/// <summary>
/// 主数据库
/// </summary>
public DbConnectionOptions MassterDB { get; set; }
/// <summary>
/// 从数据库
/// </summary>
public List<DbConnectionOptions> ReadDB { get; set; }
}
/// <summary>
/// 数据库配置选项,定义数据库连接字符串、数据库类型和访问权重
/// </summary>
public class DbConnectionOptions
{
/// <summary>
/// 数据库连接字符
/// </summary>
public string ConnectionString { get; set; }
/// <summary>
/// 数据库类型
/// </summary>
public DatabaseType DatabaseType { get; set; }
/// <summary>
/// 访问权重,值越大权重越低
/// </summary>
public int DbLevel { get; set; }
}
}

23
Znyc.Cloudcar.Admin.Commons/Core/DataManager/WriteAndReadEnum.cs

@ -0,0 +1,23 @@
namespace Znyc.Cloudcar.Admin.Commons.DataManager
{
/// <summary>
/// 数据库读、写操作枚举
/// </summary>
public enum WriteAndReadEnum
{
/// <summary>
/// 写操作
/// </summary>
Write,
/// <summary>
/// 读操作
/// </summary>
Read,
/// <summary>
/// 默认,不区分读写
/// </summary>
Default
}
}

18
Znyc.Cloudcar.Admin.Commons/Core/DataManager/YuebonDbOptions.cs

@ -0,0 +1,18 @@
using System.Collections.Generic;
using Znyc.Cloudcar.Admin.Commons.Enums;
namespace Znyc.Cloudcar.Admin.Commons.Core.DataManager
{
public class ZnycDbOptions
{
/// <summary>
/// 默认数据库类型
/// </summary>
public DatabaseType DefaultDatabaseType { get; set; } = DatabaseType.SqlServer;
/// <summary>
/// 数据库连接配置
/// </summary>
public IDictionary<string, DbConnectionOptions> DbConnections { get; set; }
}
}

64
Znyc.Cloudcar.Admin.Commons/Core/DataManager/YuebonDbOptionsSetup.cs

@ -0,0 +1,64 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Znyc.Cloudcar.Admin.Commons.Core.DataManager
{
public class ZnycDbOptionsSetup : IConfigureOptions<ZnycDbOptions>
{
private readonly IConfiguration _configuration;
public ZnycDbOptionsSetup(IConfiguration configuration)
{
_configuration = configuration;
}
/// <summary>
/// 配置options各属性信息
/// </summary>
/// <param name="options"></param>
public void Configure(ZnycDbOptions options)
{
SetDbConnectionsOptions(options);
}
private void SetDbConnectionsOptions(ZnycDbOptions options)
{
Dictionary<string, DbConnectionOptions> dbConnectionMap = new Dictionary<string, DbConnectionOptions>();
options.DbConnections = dbConnectionMap;
string dbConfigName = Configs.GetConfigurationValue("AppSetting", "DefaultDataBase");
IConfiguration section = _configuration.GetSection("DbConnections:" + dbConfigName);
Dictionary<string, DbConnectionOptions> dict = section.Get<Dictionary<string, DbConnectionOptions>>();
if (dict == null || dict.Count == 0)
{
string connectionString = _configuration["ConnectionStrings:DefaultDbContext"];
if (connectionString == null)
{
return;
}
dbConnectionMap.Add("DefaultDb", new DbConnectionOptions
{
ConnectionString = connectionString,
DatabaseType = options.DefaultDatabaseType
});
return;
}
IGrouping<string, string> ambiguous = dict.Keys.GroupBy(d => d).FirstOrDefault(d => d.Count() > 1);
if (ambiguous != null)
{
throw new Exception($"数据上下文配置中存在多个配置节点拥有同一个数据库连接名称,存在二义性:{ambiguous.First()}");
}
foreach (KeyValuePair<string, DbConnectionOptions> db in dict)
{
dbConnectionMap.Add(db.Key, db.Value);
}
}
}
}

796
Znyc.Cloudcar.Admin.Commons/Core/DbContextCore/BaseDbContext.cs

@ -0,0 +1,796 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;
using Znyc.Cloudcar.Admin.Commons.Attributes;
using Znyc.Cloudcar.Admin.Commons.Core.DataManager;
using Znyc.Cloudcar.Admin.Commons.Entitys;
using Znyc.Cloudcar.Admin.Commons.Enums;
using Znyc.Cloudcar.Admin.Commons.Helpers;
using Znyc.Cloudcar.Admin.Commons.IDbContext;
using Znyc.Cloudcar.Admin.Commons.Pages;
namespace Znyc.Cloudcar.Admin.Commons.DbContextCore
{
/// <summary>
/// DbContext上下文的实现
/// </summary>
public class BaseDbContext : DbContext, IDbContextCore
{
/// <summary>
/// </summary>
protected BaseDbContext()
{
}
/// <summary>
/// </summary>
/// <param name="dbConnectionOptions"></param>
public BaseDbContext(DbConnectionOptions dbConnectionOptions)
{
this.dbConnectionOptions = dbConnectionOptions;
}
/// <summary>
/// 配置,初始化数据库引擎
/// </summary>
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (dbConnectionOptions == null)
{
dbConnectionOptions = DBServerProvider.GeDbConnectionOptions();
}
string defaultSqlConnectionString = dbConnectionOptions.ConnectionString;
DatabaseType dbType = dbConnectionOptions.DatabaseType;
if (dbType == DatabaseType.SqlServer)
{
optionsBuilder.UseSqlServer(defaultSqlConnectionString);
}
else if (dbType == DatabaseType.MySql)
{
optionsBuilder.UseMySql(defaultSqlConnectionString, new MySqlServerVersion(new Version(5, 7, 1)));
}
else if (dbType == DatabaseType.Oracle)
{
optionsBuilder.UseOracle(defaultSqlConnectionString);
}
else if (dbType == DatabaseType.SQLite)
{
optionsBuilder.UseSqlite(defaultSqlConnectionString);
}
else if (dbType == DatabaseType.Npgsql)
{
optionsBuilder.UseNpgsql(defaultSqlConnectionString);
}
else
{
throw new NotSupportedException("The database is not supported");
}
//使用查询跟踪行为
optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
base.OnConfiguring(optionsBuilder);
}
/// <summary>
/// 模型创建
/// </summary>
/// <param name="modelBuilder"></param>
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
MappingEntityTypes(modelBuilder);
base.OnModelCreating(modelBuilder);
}
/// <summary>
/// </summary>
/// <param name="modelBuilder"></param>
private void MappingEntityTypes(ModelBuilder modelBuilder)
{
IList<Assembly> assemblies = RuntimeHelper.GetAllZnycAssemblies();
foreach (Assembly assembly in assemblies)
{
IEnumerable<Type> entityTypes = assembly.GetTypes()
.Where(type => !string.IsNullOrWhiteSpace(type.Namespace))
.Where(type => type.IsClass)
.Where(type => type.BaseType != null)
.Where(type => typeof(Entity).IsAssignableFrom(type) || type.IsSubclassOf(typeof(BaseViewModel)));
foreach (Type entityType in entityTypes)
{
if (modelBuilder.Model.FindEntityType(entityType) != null || entityType.Name == "Entity" ||
entityType.Name == "BaseEntity`1")
{
continue;
}
TableAttribute table = entityType.GetCustomAttributes<TableAttribute>().FirstOrDefault();
modelBuilder.Model.AddEntityType(entityType).SetTableName(table.Name);
IMutableEntityType ientityTypes = modelBuilder.Model.FindEntityType(entityType);
ShardingTableAttribute attr = entityType.GetCustomAttributes<ShardingTableAttribute>().FirstOrDefault();
if (attr != null && entityType != null)
{
modelBuilder.Model.FindEntityType(entityType)
.SetTableName($"{entityType.Name}{attr.Splitter}{DateTime.Now.ToString(attr.Suffix)}");
}
if (typeof(IDeleteAudited).IsAssignableFrom(typeof(Entity)))
{
modelBuilder.Entity<Entity>().HasQueryFilter(m => ((IDeleteAudited)m).IsDeleted == false);
}
if (IsMultiTenant)
{
if (typeof(IMustHaveTenant).IsAssignableFrom(typeof(Entity)))
{
modelBuilder.Entity<Entity>().HasQueryFilter(m => ((IMustHaveTenant)m).TenantId == "");
}
}
}
}
}
#region 基础参数
/// <summary>
/// 数据库配置名称,可在子类指定不同的配置名称,用于访问不同的数据库
/// </summary>
protected string dbConfigName = "";
/// <summary>
/// 是否开启多租户
/// </summary>
protected bool isMultiTenant = false;
/// <summary>
/// </summary>
protected DbConnectionOptions dbConnectionOptions;
/// <summary>
/// 数据库访问对象的外键约束
/// </summary>
public bool IsMultiTenant => isMultiTenant;
/// <summary>
/// </summary>
/// <returns></returns>
public DatabaseFacade GetDatabase()
{
return Database;
}
#endregion 基础参数
#region 接口实现
/// <summary>
/// 新增实体
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entity"></param>
/// <returns></returns>
public new virtual int Add<T>(T entity) where T : class
{
base.Add(entity);
return SaveChanges();
}
/// <summary>
/// 新增实体
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entity"></param>
/// <returns></returns>
public virtual async Task<int> AddAsync<T>(T entity) where T : class
{
await base.AddAsync(entity);
return await SaveChangesAsync();
}
/// <summary>
/// 批量新增
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entities"></param>
/// <returns></returns>
public virtual int AddRange<T>(ICollection<T> entities) where T : class
{
base.AddRange(entities);
return SaveChanges();
}
/// <summary>
/// 批量新增
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entities"></param>
/// <returns></returns>
public virtual async Task<int> AddRangeAsync<T>(ICollection<T> entities) where T : class
{
await base.AddRangeAsync(entities);
return await SaveChangesAsync();
}
/// <summary>
/// 统计数量Count()
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="where">查询条件</param>
/// <returns></returns>
public virtual int Count<T>(Expression<Func<T, bool>> where = null) where T : class
{
return where == null ? GetDbSet<T>().Count() : GetDbSet<T>().Count(where);
}
/// <summary>
/// 统计数量Count()
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="where">查询条件</param>
/// <returns></returns>
public virtual async Task<int> CountAsync<T>(Expression<Func<T, bool>> where = null) where T : class
{
return await (where == null ? GetDbSet<T>().CountAsync() : GetDbSet<T>().CountAsync(where));
}
/// <summary>
/// 物理删除数据
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TKey">主键类型</typeparam>
/// <param name="key">主键</param>
/// <returns></returns>
public virtual int Delete<T, TKey>(TKey key) where T : Entity
{
T entity = Find<T>(key);
Remove(entity);
return SaveChanges();
}
/// <summary>
/// 执行Sql,返回影响记录行数
/// </summary>
/// <param name="sql"></param>
/// <param name="parameters"></param>
/// <returns></returns>
public virtual int ExecuteSqlWithNonQuery(string sql, params object[] parameters)
{
return Database.ExecuteSqlRaw(sql, parameters);
}
/// <summary>
/// 执行Sql,返回影响记录行数
/// </summary>
/// <param name="sql"></param>
/// <param name="parameters"></param>
/// <returns></returns>
public virtual async Task<int> ExecuteSqlWithNonQueryAsync(string sql, params object[] parameters)
{
return await Database.ExecuteSqlRawAsync(sql, parameters);
}
/// <summary>
/// 编辑更新保存实体
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entity"></param>
/// <returns></returns>
public virtual int Edit<T>(T entity) where T : class
{
base.Update(entity);
base.Entry(entity).State = EntityState.Modified;
return SaveChanges();
}
/// <summary>
/// 批量更新保存实体
/// 以添加状态开始跟踪给定的实体和任何其他尚未被跟踪的可访问实体
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entities"></param>
/// <returns></returns>
public virtual int EditRange<T>(ICollection<T> entities) where T : class
{
GetDbSet<T>().AttachRange(entities.ToArray());
return SaveChanges();
}
/// <summary>
/// 是否存在,存在返回true,不存在返回false
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="where">查询条件</param>
/// <returns></returns>
public virtual bool Exist<T>(Expression<Func<T, bool>> where = null) where T : class
{
return where == null ? GetDbSet<T>().Any() : GetDbSet<T>().Any(where);
}
/// <summary>
/// 是否存在,存在返回true,不存在返回false
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="where"></param>
/// <returns></returns>
public virtual async Task<bool> ExistAsync<T>(Expression<Func<T, bool>> where = null) where T : class
{
return await Task.FromResult(Exist(where));
}
/// <summary>
/// 根据条件进行查询数据
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="include"></param>
/// <param name="where">查询条件</param>
/// <returns></returns>
public virtual IQueryable<T> FilterWithInclude<T>(Func<IQueryable<T>, IQueryable<T>> include,
Expression<Func<T, bool>> where) where T : class
{
IQueryable<T> result = GetDbSet<T>().AsQueryable();
if (where != null)
{
result = GetDbSet<T>().Where(@where);
}
if (include != null)
{
result = include(result);
}
return result;
}
/// <summary>
/// 根据主键查询实体
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
public virtual T Find<T>(object key) where T : class
{
return base.Find<T>(key);
}
/// <summary>
/// 根据主键查询实体
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
public virtual T Find<T>(string key) where T : class
{
return base.Find<T>(key);
}
/// <summary>
/// 根据主键查询实体
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TKey"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
public virtual T Find<T, TKey>(TKey key) where T : Entity
{
return base.Find<T>(key);
}
/// <summary>
/// 根据主键查询实体
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
public virtual async Task<T> FindAsync<T>(object key) where T : class
{
return await base.FindAsync<T>(key);
}
/// <summary>
/// 根据主键查询实体
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TKey"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
public virtual async Task<T> FindAsync<T, TKey>(TKey key) where T : Entity
{
return await base.FindAsync<T>(key);
}
/// <summary>
/// 根据条件查询实体,返回实体集合
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="where">查询条件</param>
/// <param name="asNoTracking">是否启用模型跟踪,默认为false不跟踪</param>
/// <returns></returns>
public virtual IQueryable<T> Get<T>(Expression<Func<T, bool>> where = null, bool asNoTracking = false)
where T : class
{
IQueryable<T> query = GetDbSet<T>().AsQueryable();
if (where != null)
{
query = query.Where(@where);
}
if (asNoTracking)
{
query = query.AsNoTracking();
}
return query;
}
/// <summary>
/// 获取所有实体类型
/// </summary>
/// <returns></returns>
public virtual List<IEntityType> GetAllEntityTypes()
{
return Model.GetEntityTypes().ToList();
}
/// <summary>
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public virtual DbSet<T> GetDbSet<T>() where T : class
{
if (Model.FindEntityType(typeof(T)) != null)
{
return Set<T>();
}
throw new Exception(
$"类型{typeof(T).Name}未在数据库上下文中注册,请先在DbContextOption设置ModelAssemblyName以将所有实体类型注册到数据库上下文中。");
}
/// <summary>
/// 根据条件查询一个实体,
/// 检验序列中是否包含有元素。引用类型的默认值default(T)为null,表示在序列中没有找到元素。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="where">查询条件</param>
/// <returns></returns>
public virtual T GetSingleOrDefault<T>(Expression<Func<T, bool>> where = null) where T : class
{
return where == null ? GetDbSet<T>().SingleOrDefault() : GetDbSet<T>().SingleOrDefault(where);
}
/// <summary>
/// 根据条件查询一个实体,
/// 检验序列中是否包含有元素。引用类型的默认值default(T)为null,表示在序列中没有找到元素。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="where">查询条件</param>
/// <returns></returns>
public virtual async Task<T> GetSingleOrDefaultAsync<T>(Expression<Func<T, bool>> where = null) where T : class
{
return await (where == null
? GetDbSet<T>().SingleOrDefaultAsync()
: GetDbSet<T>().SingleOrDefaultAsync(where));
}
/// <summary>
/// 根据条件查询一个实体,
/// 异步返回序列的第一个元素,如果序列不包含元素,则返回默认值。
/// 引用类型的默认值default(T)为null,表示在序列中没有找到元素。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="where">查询条件</param>
/// <returns></returns>
public virtual async Task<T> GetFirstOrDefaultAsync<T>(Expression<Func<T, bool>> where = null) where T : class
{
return await (where == null
? GetDbSet<T>().FirstOrDefaultAsync()
: GetDbSet<T>().FirstOrDefaultAsync(where));
}
/// <summary>
/// 更新指定字段的值
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="model">数据实体</param>
/// <param name="updateColumns">指定字段</param>
/// <returns></returns>
public virtual int Update<T>(T model, params string[] updateColumns) where T : class
{
if (updateColumns != null && updateColumns.Length > 0)
{
if (Entry(model).State == EntityState.Added ||
Entry(model).State == EntityState.Detached)
{
GetDbSet<T>().Attach(model);
}
foreach (string propertyName in updateColumns)
{
Entry(model).Property(propertyName).IsModified = true;
}
}
else
{
Entry(model).State = EntityState.Modified;
}
return SaveChanges();
}
/// <summary>
/// 批量插入
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entities">数据实体集合</param>
/// <param name="destinationTableName">数据库表名称</param>
public virtual void BulkInsert<T>(IList<T> entities, string destinationTableName = null) where T : class
{
if (!Database.IsSqlServer() && !Database.IsMySql())
{
throw new NotSupportedException("This method only supports for SQL Server or MySql.");
}
}
/// <summary>
/// Sql查询,并返回实体
/// </summary>
/// <typeparam name="T">查询对象实体</typeparam>
/// <typeparam name="TView">返回/输出实体</typeparam>
/// <param name="sql">sql语句</param>
/// <param name="parameters">SQL参数</param>
/// <returns></returns>
public virtual List<TView> SqlQuery<T, TView>(string sql, params object[] parameters)
where T : class
{
return GetDbSet<T>().FromSqlRaw(sql, parameters).Cast<TView>().ToList();
}
/// <summary>
/// Sql查询,并返回实体
/// </summary>
/// <typeparam name="T">查询对象实体</typeparam>
/// <typeparam name="TView">返回/输出实体</typeparam>
/// <param name="sql">sql语句</param>
/// <param name="parameters">SQL参数</param>
/// <returns></returns>
public virtual async Task<List<TView>> SqlQueryAsync<T, TView>(string sql, params object[] parameters)
where T : class
where TView : class
{
return await GetDbSet<T>().FromSqlRaw(sql, parameters).Cast<TView>().ToListAsync();
}
/// <summary>
/// 分页查询,SQL语句查询,返回指定输出对象集合
/// </summary>
/// <typeparam name="T">查询对象实体</typeparam>
/// <typeparam name="TView">返回/输出实体</typeparam>
/// <param name="sql">sql语句</param>
/// <param name="orderBys">排序条件</param>
/// <param name="pageIndex">当前页</param>
/// <param name="pageSize">每页显示数量</param>
/// <param name="eachAction"></param>
/// <returns></returns>
public virtual PageResult<T> SqlQueryByPagination<T, TView>(string sql, string[] orderBys, int pageIndex,
int pageSize,
Action<TView> eachAction = null) where T : class where TView : class
{
throw new NotImplementedException();
}
/// <summary>
/// 分页查询,SQL语句查询,返回数据实体集合
/// </summary>
/// <typeparam name="T">查询对象实体</typeparam>
/// <param name="sql">sql语句</param>
/// <param name="orderBys">排序条件</param>
/// <param name="pageIndex">当前页</param>
/// <param name="pageSize">每页显示数量</param>
/// <param name="parameters">查询SQL参数</param>
/// <returns></returns>
public virtual PageResult<T> SqlQueryByPagination<T>(string sql, string[] orderBys, int pageIndex, int pageSize,
params DbParameter[] parameters) where T : class, new()
{
throw new NotImplementedException();
}
#region 显式编译的查询,提高查询性能
/// <summary>
/// 根据主键查询返回一个实体,该方法是显式编译的查询
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TKey">主键类型</typeparam>
/// <param name="id">主键值</param>
/// <returns></returns>
public T GetByCompileQuery<T, TKey>(TKey id) where T : Entity
{
return EF.CompileQuery((DbContext context, TKey id) => context.Set<T>().Find(id))(this, id);
}
/// <summary>
/// 根据主键查询返回一个实体,该方法是显式编译的查询
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TKey">主键类型</typeparam>
/// <param name="id">主键值</param>
/// <returns></returns>
public Task<T> GetByCompileQueryAsync<T, TKey>(TKey id) where T : Entity
{
return EF.CompileAsyncQuery((DbContext context, TKey id) => context.Set<T>().Find(id))(this, id);
}
/// <summary>
/// 根据条件查询返回实体集合,该方法是显式编译的查询
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="filter">查询条件</param>
/// <returns></returns>
public IList<T> GetByCompileQuery<T>(Expression<Func<T, bool>> filter) where T : class
{
if (filter == null)
{
filter = m => true;
}
return EF.CompileQuery((DbContext context) => context.Set<T>().AsNoTracking().Where(filter).ToList())(this);
}
/// <summary>
/// 根据条件查询返回实体集合,该方法是显式编译的查询
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="filter">查询条件</param>
/// <returns></returns>
public Task<List<T>> GetByCompileQueryAsync<T>(Expression<Func<T, bool>> filter) where T : class
{
if (filter == null)
{
filter = m => true;
}
return EF.CompileAsyncQuery((DbContext context) =>
context.Set<T>().AsNoTracking().Where(filter).ToList())(this);
}
/// <summary>
/// 根据条件查询一个实体,该方法是显式编译的查询
/// 检验序列中是否包含有元素。引用类型的默认值default(T)为null,表示在序列中没有找到元素。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="filter">查询条件</param>
/// <returns></returns>
public T FirstOrDefaultByCompileQuery<T>(Expression<Func<T, bool>> filter) where T : class
{
if (filter == null)
{
filter = m => true;
}
return EF.CompileQuery((DbContext context) => context.Set<T>().AsNoTracking().FirstOrDefault(filter))(this);
}
/// <summary>
/// 根据条件查询一个实体,该方法是显式编译的查询
/// 检验序列中是否包含有元素。引用类型的默认值default(T)为null,表示在序列中没有找到元素。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="filter">查询条件</param>
/// <returns></returns>
public Task<T> FirstOrDefaultByCompileQueryAsync<T>(Expression<Func<T, bool>> filter) where T : class
{
if (filter == null)
{
filter = m => true;
}
return EF.CompileAsyncQuery((DbContext context) =>
context.Set<T>().AsNoTracking().FirstOrDefault(filter))(this);
}
/// <summary>
/// 根据条件查询一个实体,启用模型跟踪,该方法是显式编译的查询
/// 检验序列中是否包含有元素。引用类型的默认值default(T)为null,表示在序列中没有找到元素。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="filter">查询条件</param>
/// <returns></returns>
public T FirstOrDefaultWithTrackingByCompileQuery<T>(Expression<Func<T, bool>> filter) where T : class
{
if (filter == null)
{
filter = m => true;
}
return EF.CompileQuery((DbContext context) => context.Set<T>().FirstOrDefault(filter))(this);
}
/// <summary>
/// 根据条件查询一个实体,启用模型跟踪,该方法是显式编译的查询
/// 检验序列中是否包含有元素。引用类型的默认值default(T)为null,表示在序列中没有找到元素。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="filter">查询条件</param>
/// <returns></returns>
public Task<T> FirstOrDefaultWithTrackingByCompileQueryAsync<T>(Expression<Func<T, bool>> filter)
where T : class
{
if (filter == null)
{
filter = m => true;
}
return EF.CompileAsyncQuery((DbContext context) => context.Set<T>().FirstOrDefault(filter))(this);
}
/// <summary>
/// 统计数量Count(),该方法是显式编译的查询
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="filter">查询条件</param>
/// <returns></returns>
public int CountByCompileQuery<T>(Expression<Func<T, bool>> filter) where T : class
{
if (filter == null)
{
filter = m => true;
}
return EF.CompileQuery((DbContext context) => context.Set<T>().Count(filter))(this);
}
/// <summary>
/// 统计数量Count(),该方法是显式编译的查询
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="filter">查询条件</param>
/// <returns></returns>
public Task<int> CountByCompileQueryAsync<T>(Expression<Func<T, bool>> filter) where T : class
{
if (filter == null)
{
filter = m => true;
}
return EF.CompileAsyncQuery((DbContext context) => context.Set<T>().Count(filter))(this);
}
/// <summary>
/// 根据sql语句返回DataTable数据
/// </summary>
/// <param name="sql">Sql语句</param>
/// <param name="cmdTimeout">执行超时时间,默认30毫秒</param>
/// <param name="parameters">DbParameter[]参数</param>
/// <returns></returns>
public virtual DataTable GetDataTable(string sql, int cmdTimeout = 30, params DbParameter[] parameters)
{
throw new NotImplementedException();
}
/// <summary>
/// 根据sql语句返回List数据
/// </summary>
/// <param name="sql">Sql语句</param>
/// <param name="cmdTimeout">执行超时时间,默认30毫秒</param>
/// <param name="parameters">DbParameter[] 参数</param>
/// <returns></returns>
public virtual List<DataTable> GetDataTables(string sql, int cmdTimeout = 30, params DbParameter[] parameters)
{
throw new NotImplementedException();
}
#endregion 显式编译的查询,提高查询性能
#endregion 接口实现
}
}

101
Znyc.Cloudcar.Admin.Commons/Core/DbContextCore/DbContextFactory.cs

@ -0,0 +1,101 @@
using Microsoft.Extensions.DependencyInjection;
using Znyc.Cloudcar.Admin.Commons.Core.DataManager;
using Znyc.Cloudcar.Admin.Commons.DataManager;
using Znyc.Cloudcar.Admin.Commons.Extensions;
using Znyc.Cloudcar.Admin.Commons.IDbContext;
using Znyc.Cloudcar.Admin.Commons.Options;
namespace Znyc.Cloudcar.Admin.Commons.DbContextCore
{
/// <summary>
/// 上下文工厂类
/// </summary>
public class DbContextFactory : IDbContextFactory
{
/// <summary>
/// </summary>
public static DbContextFactory Instance => new();
/// <summary>
/// 服务
/// </summary>
public IServiceCollection ServiceCollection { get; set; }
/// <summary>
/// 创建数据库读写上下文
/// </summary>
/// <param name="writeAndRead">指定读、写操作</param>
/// <returns></returns>
public BaseDbContext CreateContext(WriteAndReadEnum writeAndRead)
{
DbConnectionOptions dbConnectionOptions = new DbConnectionOptions();
switch (writeAndRead)
{
case WriteAndReadEnum.Write:
dbConnectionOptions = DBServerProvider.GeDbConnectionOptions();
break;
case WriteAndReadEnum.Read:
dbConnectionOptions = DBServerProvider.GeDbConnectionOptions(false);
break;
default:
dbConnectionOptions = DBServerProvider.GeDbConnectionOptions();
break;
}
return new BaseDbContext(dbConnectionOptions);
}
/// <summary>
/// 创建数据库读写上下文
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="writeAndRead">指定读、写操作</param>
/// <returns></returns>
public BaseDbContext CreateContext<TEntity>(WriteAndReadEnum writeAndRead)
{
DbConnectionOptions dbConnectionOptions = new DbConnectionOptions();
switch (writeAndRead)
{
case WriteAndReadEnum.Write:
dbConnectionOptions = DBServerProvider.GeDbConnectionOptions<TEntity>();
break;
case WriteAndReadEnum.Read:
dbConnectionOptions = DBServerProvider.GeDbConnectionOptions<TEntity>(false);
break;
default:
dbConnectionOptions = DBServerProvider.GeDbConnectionOptions<TEntity>();
break;
}
return new BaseDbContext(dbConnectionOptions);
}
/// <summary>
/// 向服务注入上下文
/// </summary>
/// <typeparam name="TContext"></typeparam>
/// <param name="option"></param>
public void AddDbContext<TContext>(DbContextOption option)
where TContext : BaseDbContext, IDbContextCore
{
ServiceCollection.AddDbContext<IDbContextCore, TContext>(option);
}
/// <summary>
/// 向服务注入上下文
/// </summary>
/// <typeparam name="ITContext">上下文接口</typeparam>
/// <typeparam name="TContext">上下文实现类</typeparam>
/// <param name="option"></param>
public void AddDbContext<ITContext, TContext>(DbContextOption option)
where ITContext : IDbContextCore
where TContext : BaseDbContext, ITContext
{
ServiceCollection.AddDbContext<ITContext, TContext>(option);
}
}
}

17
Znyc.Cloudcar.Admin.Commons/Core/DbContextCore/DefaultModelBuilder.cs

@ -0,0 +1,17 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Conventions;
namespace Znyc.Cloudcar.Admin.Commons.EfDbContext
{
public class DefaultModelBuilder : ModelBuilder
{
public DefaultModelBuilder(ConventionSet conventions) : base(conventions)
{
}
public override ModelBuilder ApplyConfiguration<TEntity>(IEntityTypeConfiguration<TEntity> configuration)
{
return base.ApplyConfiguration(configuration);
}
}
}

124
Znyc.Cloudcar.Admin.Commons/Core/DbContextCore/MySqlDbContext.cs

@ -0,0 +1,124 @@
using Microsoft.EntityFrameworkCore;
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data;
using System.Data.Common;
using System.IO;
using System.Linq;
using System.Reflection;
using Znyc.Cloudcar.Admin.Commons.Extensions;
using Znyc.Cloudcar.Admin.Commons.IDbContext;
namespace Znyc.Cloudcar.Admin.Commons.DbContextCore
{
/// <summary>
/// </summary>
public class MySqlDbContext : BaseDbContext, IMySqlDbContext
{
/// <summary>
/// 批量插入
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entities">数据实体集合</param>
/// <param name="destinationTableName">数据库表名称</param>
public override void BulkInsert<T>(IList<T> entities, string destinationTableName = null)
{
if (entities == null || !entities.Any())
{
return;
}
if (string.IsNullOrEmpty(destinationTableName))
{
string mappingTableName = typeof(T).GetCustomAttribute<TableAttribute>()?.Name;
destinationTableName = string.IsNullOrEmpty(mappingTableName) ? typeof(T).Name : mappingTableName;
}
MySqlBulkInsert(entities, destinationTableName);
}
public override DataTable GetDataTable(string sql, int cmdTimeout = 30, params DbParameter[] parameters)
{
return GetDataTables(sql, cmdTimeout, parameters).FirstOrDefault();
}
public override List<DataTable> GetDataTables(string sql, int cmdTimeout = 30, params DbParameter[] parameters)
{
List<DataTable> dts = new List<DataTable>();
//TODO: connection 不能dispose 或者 用using,否则下次获取connection会报错提示“the connectionstring property has not been initialized。”
DbConnection connection = Database.GetDbConnection();
if (connection.State != ConnectionState.Open)
{
connection.Open();
}
using (MySqlCommand cmd = new MySqlCommand(sql, (MySqlConnection)connection))
{
cmd.CommandTimeout = cmdTimeout;
if (parameters != null && parameters.Length > 0)
{
cmd.Parameters.AddRange(parameters);
}
using (MySqlDataAdapter da = new MySqlDataAdapter(cmd))
{
using (DataSet ds = new DataSet())
{
da.Fill(ds);
foreach (DataTable table in ds.Tables)
{
dts.Add(table);
}
}
}
}
connection.Close();
return dts;
}
/// <summary>
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entities"></param>
/// <param name="destinationTableName"></param>
private void MySqlBulkInsert<T>(IList<T> entities, string destinationTableName) where T : class
{
string tmpDir = Path.Combine(AppContext.BaseDirectory, "Temp");
if (!Directory.Exists(tmpDir))
{
Directory.CreateDirectory(tmpDir);
}
string csvFileName = Path.Combine(tmpDir, $"{DateTime.Now:yyyyMMddHHmmssfff}.csv");
if (!File.Exists(csvFileName))
{
File.Create(csvFileName);
}
string separator = ",";
entities.SaveToCsv(csvFileName, separator);
MySqlConnection conn = (MySqlConnection)Database.GetDbConnection();
if (conn.State != ConnectionState.Open)
{
conn.Open();
}
MySqlBulkLoader bulk = new MySqlBulkLoader(conn)
{
NumberOfLinesToSkip = 0,
TableName = destinationTableName,
FieldTerminator = separator,
FieldQuotationCharacter = '"',
EscapeCharacter = '"',
LineTerminator = "\r\n"
};
bulk.LoadAsync();
conn.Close();
File.Delete(csvFileName);
}
}
}

69
Znyc.Cloudcar.Admin.Commons/Core/DbContextCore/OracleDbContext.cs

@ -0,0 +1,69 @@
using Microsoft.EntityFrameworkCore;
using Oracle.ManagedDataAccess.Client;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using Znyc.Cloudcar.Admin.Commons.IDbContext;
namespace Znyc.Cloudcar.Admin.Commons.DbContextCore
{
/// <summary>
/// Oracle上下文
/// </summary>
public class OracleDbContext : BaseDbContext, IOracleDbContext
{
/// <summary>
/// </summary>
/// <param name="sql"></param>
/// <param name="cmdTimeout"></param>
/// <param name="parameters"></param>
/// <returns></returns>
public override DataTable GetDataTable(string sql, int cmdTimeout = 30, params DbParameter[] parameters)
{
return GetDataTables(sql, cmdTimeout, parameters).FirstOrDefault();
}
/// <summary>
/// </summary>
/// <param name="sql"></param>
/// <param name="cmdTimeout"></param>
/// <param name="parameters"></param>
/// <returns></returns>
public override List<DataTable> GetDataTables(string sql, int cmdTimeout = 30, params DbParameter[] parameters)
{
List<DataTable> dts = new List<DataTable>();
//TODO: connection 不能dispose 或者 用using,否则下次获取connection会报错提示“the connectionstring property has not been initialized。”
DbConnection connection = Database.GetDbConnection();
if (connection.State != ConnectionState.Open)
{
connection.Open();
}
using (OracleCommand cmd = new OracleCommand(sql, (OracleConnection)connection))
{
cmd.CommandTimeout = cmdTimeout;
if (parameters != null && parameters.Length > 0)
{
cmd.Parameters.AddRange(parameters);
}
using (OracleDataAdapter da = new OracleDataAdapter(cmd))
{
using (DataSet ds = new DataSet())
{
da.Fill(ds);
foreach (DataTable table in ds.Tables)
{
dts.Add(table);
}
}
}
}
connection.Close();
return dts;
}
}
}

80
Znyc.Cloudcar.Admin.Commons/Core/DbContextCore/PostgreSQLDbContext.cs

@ -0,0 +1,80 @@
using Microsoft.EntityFrameworkCore;
using Npgsql;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using Znyc.Cloudcar.Admin.Commons.Encrypt;
using Znyc.Cloudcar.Admin.Commons.Extensions;
using Znyc.Cloudcar.Admin.Commons.IDbContext;
namespace Znyc.Cloudcar.Admin.Commons.DbContextCore
{
public class PostgreSQLDbContext : BaseDbContext, IPostgreSQLDbContext
{
public override DataTable GetDataTable(string sql, int cmdTimeout = 30, params DbParameter[] parameters)
{
return GetDataTables(sql, cmdTimeout, parameters).FirstOrDefault();
}
public override List<DataTable> GetDataTables(string sql, int cmdTimeout = 30, params DbParameter[] parameters)
{
List<DataTable> dts = new List<DataTable>();
//TODO: connection 不能dispose 或者 用using,否则下次获取connection会报错提示“the connectionstring property has not been initialized。”
DbConnection connection = Database.GetDbConnection();
if (connection.State != ConnectionState.Open)
{
connection.Open();
}
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, (NpgsqlConnection)connection))
{
cmd.CommandTimeout = cmdTimeout;
if (parameters != null && parameters.Length > 0)
{
cmd.Parameters.AddRange(parameters);
}
using (NpgsqlDataAdapter da = new NpgsqlDataAdapter(cmd))
{
using (DataSet ds = new DataSet())
{
da.Fill(ds);
foreach (DataTable table in ds.Tables)
{
dts.Add(table);
}
}
}
}
connection.Close();
return dts;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
string conStringEncrypt = Configs.GetConfigurationValue("AppSetting", "ConStringEncrypt");
isMultiTenant = Configs.GetConfigurationValue("AppSetting", "IsMultiTenant").ToBool();
if (string.IsNullOrEmpty(dbConfigName))
{
dbConfigName = Configs.GetConfigurationValue("AppSetting", "DefaultDataBase");
}
string defaultSqlConnectionString = Configs.GetConnectionString(dbConfigName);
if (conStringEncrypt == "true")
{
defaultSqlConnectionString = DEncrypt.Decrypt(defaultSqlConnectionString);
}
string dbType = dbConfigName.ToUpper();
if (dbType.Contains("NPGSQL"))
{
optionsBuilder.UseNpgsql(defaultSqlConnectionString);
}
base.OnConfiguring(optionsBuilder);
}
}
}

62
Znyc.Cloudcar.Admin.Commons/Core/DbContextCore/SQLiteDbContext.cs

@ -0,0 +1,62 @@
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using Znyc.Cloudcar.Admin.Commons.IDbContext;
namespace Znyc.Cloudcar.Admin.Commons.DbContextCore
{
/// <summary>
/// SQLite数据库操作
/// </summary>
public class SQLiteDbContext : BaseDbContext, ISQLiteDbContext
{
/// <summary>
/// </summary>
/// <param name="sql"></param>
/// <param name="cmdTimeout"></param>
/// <param name="parameters"></param>
/// <returns></returns>
public override DataTable GetDataTable(string sql, int cmdTimeout = 30, params DbParameter[] parameters)
{
return GetDataTables(sql, cmdTimeout, parameters).FirstOrDefault();
}
/// <summary>
/// </summary>
/// <param name="sql"></param>
/// <param name="cmdTimeout"></param>
/// <param name="parameters"></param>
/// <returns></returns>
public override List<DataTable> GetDataTables(string sql, int cmdTimeout = 30, params DbParameter[] parameters)
{
List<DataTable> dts = new List<DataTable>();
//TODO: connection 不能dispose 或者 用using,否则下次获取connection会报错提示“the connectionstring property has not been initialized。”
DbConnection connection = Database.GetDbConnection();
if (connection.State != ConnectionState.Open)
{
connection.Open();
}
using (SqliteCommand cmd = new SqliteCommand(sql, (SqliteConnection)connection))
{
cmd.CommandTimeout = cmdTimeout;
if (parameters != null && parameters.Length > 0)
{
cmd.Parameters.AddRange(parameters);
}
using (SqliteDataReader reader = cmd.ExecuteReader())
{
dts.Add(reader.GetSchemaTable());
}
}
connection.Close();
return dts;
}
}
}

225
Znyc.Cloudcar.Admin.Commons/Core/DbContextCore/SqlServerDbContext.cs

@ -0,0 +1,225 @@
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Reflection;
using Znyc.Cloudcar.Admin.Commons.Extend;
using Znyc.Cloudcar.Admin.Commons.Extensions;
using Znyc.Cloudcar.Admin.Commons.Helpers;
using Znyc.Cloudcar.Admin.Commons.IDbContext;
using Znyc.Cloudcar.Admin.Commons.Pages;
namespace Znyc.Cloudcar.Admin.Commons.DbContextCore
{
/// <summary>
/// Sql Server数据库上下文
/// </summary>
public class SqlServerDbContext : BaseDbContext, ISqlServerDbContext
{
/// <summary>
/// 批量插入
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entities">数据实体集合</param>
/// <param name="destinationTableName">如果为 null,则使用 TModel 名称作为 destinationTableName</param>
/// <returns></returns>
public override void BulkInsert<T>(IList<T> entities, string destinationTableName = null)
{
if (entities == null || !entities.Any())
{
return;
}
if (string.IsNullOrEmpty(destinationTableName))
{
string mappingTableName = typeof(T).GetCustomAttribute<TableAttribute>()?.Name;
destinationTableName = string.IsNullOrEmpty(mappingTableName) ? typeof(T).Name : mappingTableName;
}
SqlBulkInsert(entities, destinationTableName);
}
/// <summary>
/// 分页查询,SQL语句查询,返回指定输出对象集合
/// </summary>
/// <typeparam name="T">查询对象实体</typeparam>
/// <typeparam name="TView">返回/输出实体</typeparam>
/// <param name="sql">sql语句</param>
/// <param name="orderBys">排序条件</param>
/// <param name="pageIndex">当前页</param>
/// <param name="pageSize">每页显示数量</param>
/// <param name="eachAction"></param>
/// <returns></returns>
public override PageResult<T> SqlQueryByPagination<T, TView>(string sql, string[] orderBys, int pageIndex,
int pageSize,
Action<TView> eachAction = null)
{
int total = SqlQuery<T, int>($"select count(1) from ({sql}) as s").FirstOrDefault();
List<TView> jsonResults = SqlQuery<T, TView>(
$"select * from (select *,row_number() over (order by {string.Join(",", orderBys)}) as RowId from ({sql}) as s) as t where RowId between {pageSize * (pageIndex - 1) + 1} and {pageSize * pageIndex} order by {string.Join(",", orderBys)}")
.ToList();
if (eachAction != null)
{
jsonResults = jsonResults.Each(eachAction).ToList();
}
return new PageResult<T>
{
CurrentPage = pageIndex,
ItemsPerPage = pageSize,
TotalItems = total
};
}
/// <summary>
/// 分页查询,SQL语句查询,返回数据实体集合
/// </summary>
/// <typeparam name="T">查询对象实体</typeparam>
/// <param name="sql">sql语句</param>
/// <param name="orderBys">排序条件</param>
/// <param name="pageIndex">当前页</param>
/// <param name="pageSize">每页显示数量</param>
/// <param name="parameters">查询SQL参数</param>
/// <returns></returns>
public override PageResult<T> SqlQueryByPagination<T>(string sql, string[] orderBys, int pageIndex,
int pageSize,
params DbParameter[] parameters)
{
int total = (int)this.ExecuteScalar($"select count(1) from ({sql}) as s");
List<T> jsonResults = GetDataTable(
$"select * from (select *,row_number() over (order by {string.Join(",", orderBys)}) as RowId from ({sql}) as s) as t where RowId between {pageSize * (pageIndex - 1) + 1} and {pageSize * pageIndex} order by {string.Join(",", orderBys)}")
.ToList<T>();
return new PageResult<T>
{
CurrentPage = pageIndex,
ItemsPerPage = pageSize,
TotalItems = total,
Items = jsonResults
};
}
/// <summary>
/// 根据sql语句返回DataTable数据
/// </summary>
/// <param name="sql">Sql语句</param>
/// <param name="cmdTimeout">执行超时时间,默认30毫秒</param>
/// <param name="parameters">DbParameter[]参数</param>
/// <returns></returns>
public override DataTable GetDataTable(string sql, int cmdTimeout = 30, params DbParameter[] parameters)
{
return GetDataTables(sql, cmdTimeout, parameters).FirstOrDefault();
}
/// <summary>
/// 根据sql语句返回List数据
/// </summary>
/// <param name="sql">Sql语句</param>
/// <param name="cmdTimeout">执行超时时间,默认30毫秒</param>
/// <param name="parameters">DbParameter[] 参数</param>
/// <returns></returns>
public override List<DataTable> GetDataTables(string sql, int cmdTimeout = 30, params DbParameter[] parameters)
{
List<DataTable> dts = new List<DataTable>();
//TODO: connection 不能dispose 或者 用using,否则下次获取connection会报错提示“the connectionstring property has not been initialized。”
DbConnection connection = Database.GetDbConnection();
if (connection.State != ConnectionState.Open)
{
connection.Open();
}
using (SqlCommand cmd = new SqlCommand(sql, (SqlConnection)connection))
{
cmd.CommandTimeout = cmdTimeout;
if (parameters != null && parameters.Length > 0)
{
cmd.Parameters.AddRange(parameters);
}
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
using (DataSet ds = new DataSet())
{
da.Fill(ds);
foreach (DataTable table in ds.Tables)
{
dts.Add(table);
}
}
}
}
connection.Close();
return dts;
}
/// <summary>
/// 批量插入
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entities">数据实体集合</param>
/// <param name="destinationTableName">如果为 null,则使用 TModel 名称作为 destinationTableName</param>
/// <returns></returns>
private void SqlBulkInsert<T>(IList<T> entities, string destinationTableName = null) where T : class
{
using (DataTable dt = entities.ToDataTable())
{
dt.TableName = destinationTableName;
SqlConnection conn = (SqlConnection)Database.GetDbConnection();
if (conn.State != ConnectionState.Open)
{
conn.Open();
}
using (SqlTransaction tran = conn.BeginTransaction())
{
try
{
SqlBulkCopy bulk = new SqlBulkCopy(conn, SqlBulkCopyOptions.Default, tran)
{
BatchSize = entities.Count,
DestinationTableName = dt.TableName
};
GenerateColumnMappings<T>(bulk.ColumnMappings);
bulk.WriteToServerAsync(dt);
tran.Commit();
}
catch (Exception)
{
tran.Rollback();
throw;
}
}
conn.Close();
}
}
/// <summary>
/// 字段与实体关系映射
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="mappings"></param>
private void GenerateColumnMappings<T>(SqlBulkCopyColumnMappingCollection mappings)
where T : class
{
PropertyInfo[] properties = typeof(T).GetProperties();
foreach (PropertyInfo property in properties)
{
if (property.GetCustomAttributes<KeyAttribute>().Any())
{
mappings.Add(new SqlBulkCopyColumnMapping(property.Name, typeof(T).Name + property.Name));
}
else
{
mappings.Add(new SqlBulkCopyColumnMapping(property.Name, property.Name));
}
}
}
}
}

16
Znyc.Cloudcar.Admin.Commons/Core/Dtos/DeletesInputDto.cs

@ -0,0 +1,16 @@
using System;
namespace Znyc.Cloudcar.Admin.Commons.Core.Dtos
{
/// <summary>
/// 批量物理删除操作传参
/// </summary>
[Serializable]
public class DeletesInputDto
{
/// <summary>
/// 主键Id集合
/// </summary>
public dynamic[] Ids { get; set; }
}
}

14
Znyc.Cloudcar.Admin.Commons/Core/Dtos/IInputDto.cs

@ -0,0 +1,14 @@
namespace Znyc.Cloudcar.Admin.Commons.Dtos
{
/// <summary>
/// 定义输入DTO
/// </summary>
/// <typeparam name="TKey"></typeparam>
public interface IInputDto<TKey>
{
/// <summary>
/// 获取或设置 主键,唯一标识
/// </summary>
TKey Id { get; set; }
}
}

9
Znyc.Cloudcar.Admin.Commons/Core/Dtos/IOutputDto.cs

@ -0,0 +1,9 @@
namespace Znyc.Cloudcar.Admin.Commons.Dtos
{
/// <summary>
/// 定义输出DTO
/// </summary>
public interface IOutputDto
{
}
}

80
Znyc.Cloudcar.Admin.Commons/Core/Dtos/InputDtoValidateExtensions.cs

@ -0,0 +1,80 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;
using Znyc.Cloudcar.Admin.Commons.Data;
using Znyc.Cloudcar.Admin.Commons.Extensions;
namespace Znyc.Cloudcar.Admin.Commons.Dtos
{
/// <summary>
/// <see cref="IInputDto{TKey}" />验证扩展
/// </summary>
public static class InputDtoValidateExtensions
{
private static readonly ConcurrentDictionary<Type, ConcurrentDictionary<PropertyInfo, ValidationAttribute[]>>
_dict
= new();
/// <summary>
/// InputDto属性验证
/// </summary>
public static void Validate<TKey>(this IEnumerable<IInputDto<TKey>> dtos)
{
IInputDto<TKey>[] inputDtos = dtos as IInputDto<TKey>[] ?? dtos.ToArray();
Check.NotNull(inputDtos, nameof(dtos));
foreach (IInputDto<TKey> dto in inputDtos)
{
Validate(dto);
}
}
/// <summary>
/// InputDto属性验证
/// </summary>
public static void Validate<TKey>(this IInputDto<TKey> dto)
{
Check.NotNull(dto, nameof(dto));
Type type = dto.GetType();
if (!_dict.TryGetValue(type, out ConcurrentDictionary<PropertyInfo, ValidationAttribute[]> dict))
{
PropertyInfo[] properties = type.GetProperties();
dict = new ConcurrentDictionary<PropertyInfo, ValidationAttribute[]>();
if (properties.Length == 0)
{
_dict[type] = dict;
return;
}
foreach (PropertyInfo property in properties)
{
dict[property] = null;
}
_dict[type] = dict;
}
foreach (PropertyInfo property in dict.Keys)
{
if (!dict.TryGetValue(property, out ValidationAttribute[] attributes) || attributes == null)
{
attributes = property.GetAttributes<ValidationAttribute>();
dict[property] = attributes;
}
if (attributes.Length == 0)
{
continue;
}
object value = property.GetValue(dto);
foreach (ValidationAttribute attribute in attributes)
{
attribute.Validate(value, property.Name);
}
}
}
}
}

39
Znyc.Cloudcar.Admin.Commons/Core/Dtos/SearchInputDto.cs

@ -0,0 +1,39 @@
using System;
using System.Runtime.Serialization;
using Znyc.Cloudcar.Admin.Commons.Pages;
namespace Znyc.Cloudcar.Admin.Commons.Dtos
{
/// <summary>
/// 查询条件公共实体类
/// </summary>
[Serializable]
[DataContract]
public class SearchInputDto<T> : PagerInfo
{
/// <summary>
/// 关键字查询
/// </summary>
public string Keywords { get; set; }
/// <summary>
/// 编码/代码
/// </summary>
public string EnCode { get; set; }
/// <summary>
/// 排序方式 默认asc
/// </summary>
public string Order { get; set; }
/// <summary>
/// 排序字段 默认Id
/// </summary>
public string Sort { get; set; } = "ModifiedTime";
/// <summary>
/// 查询条件
/// </summary>
public T Filter { get; set; }
}
}

491
Znyc.Cloudcar.Admin.Commons/Core/IDbContext/IDbContextCore.cs

@ -0,0 +1,491 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using Znyc.Cloudcar.Admin.Commons.Entitys;
using Znyc.Cloudcar.Admin.Commons.Pages;
namespace Znyc.Cloudcar.Admin.Commons.IDbContext
{
/// <summary>
/// 上下文基础接口
/// </summary>
public interface IDbContextCore : IDisposable
{
/// <summary>
/// </summary>
/// <returns></returns>
DatabaseFacade GetDatabase();
#region 删除
/// <summary>
/// 物理删除数据
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TKey">主键类型</typeparam>
/// <param name="key">主键</param>
/// <returns></returns>
int Delete<T, TKey>(TKey key) where T : Entity;
/// <summary>
/// 根据条件删除一个实体,返回影响记录行数
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="where">条件</param>
/// <returns></returns>
////int Delete<T>(Expression<Func<T, bool>> @where) where T : class;
/// <summary>
/// 根据条件删除一个实体,返回影响记录行数
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="where">条件</param>
/// <returns></returns>
//Task<int> DeleteAsync<T>(Expression<Func<T, bool>> @where) where T : class;
#endregion 删除
/// <summary>
/// 执行Sql语句,返回影响记录行数
/// </summary>
/// <param name="sql"></param>
/// <param name="parameters"></param>
/// <returns></returns>
int ExecuteSqlWithNonQuery(string sql, params object[] parameters);
/// <summary>
/// 执行Sql,返回影响记录行数
/// </summary>
/// <param name="sql"></param>
/// <param name="parameters"></param>
/// <returns></returns>
Task<int> ExecuteSqlWithNonQueryAsync(string sql, params object[] parameters);
/// <summary>
/// 批量插入
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entities">数据实体集合</param>
/// <param name="destinationTableName">数据库表名称,默认为实体名称</param>
/// <returns></returns>
void BulkInsert<T>(IList<T> entities, string destinationTableName = null)
where T : class;
/// <summary>
/// Sql查询,并返回实体集合
/// </summary>
/// <typeparam name="T">查询对象实体</typeparam>
/// <typeparam name="TView">返回/输出实体</typeparam>
/// <param name="sql">sql语句</param>
/// <param name="parameters">SQL参数</param>
/// <returns></returns>
List<TView> SqlQuery<T, TView>(string sql, params object[] parameters)
where T : class;
/// <summary>
/// Sql查询,并返回实体集合
/// </summary>
/// <typeparam name="T">查询对象实体</typeparam>
/// <typeparam name="TView">返回/输出实体</typeparam>
/// <param name="sql">sql语句</param>
/// <param name="parameters">SQL参数</param>
/// <returns></returns>
Task<List<TView>> SqlQueryAsync<T, TView>(string sql, params object[] parameters)
where T : class
where TView : class;
/// <summary>
/// 分页查询,SQL语句查询,返回指定输出对象集合
/// </summary>
/// <typeparam name="T">查询对象实体</typeparam>
/// <typeparam name="TView">返回/输出实体</typeparam>
/// <param name="sql">sql语句</param>
/// <param name="orderBys">排序条件</param>
/// <param name="pageIndex">当前页</param>
/// <param name="pageSize">每页显示数量</param>
/// <param name="eachAction"></param>
/// <returns></returns>
PageResult<T> SqlQueryByPagination<T, TView>(string sql, string[] orderBys, int pageIndex, int pageSize,
Action<TView> eachAction = null)
where T : class
where TView : class;
/// <summary>
/// 分页查询,SQL语句查询,返回数据实体集合
/// </summary>
/// <typeparam name="T">查询对象实体</typeparam>
/// <param name="sql">sql语句</param>
/// <param name="orderBys">排序条件</param>
/// <param name="pageIndex">当前页</param>
/// <param name="pageSize">每页显示数量</param>
/// <param name="parameters">查询SQL参数</param>
/// <returns></returns>
PageResult<T> SqlQueryByPagination<T>(string sql, string[] orderBys, int pageIndex, int pageSize,
params DbParameter[] parameters) where T : class, new();
/// <summary>
/// 保存到数据库
/// </summary>
/// <returns></returns>
int SaveChanges();
/// <summary>
/// 保存到数据库
/// </summary>
/// <param name="acceptAllChangesOnSuccess">更改成功发送到数据库后是否调用AcceptAllChanges()</param>
/// <returns></returns>
int SaveChanges(bool acceptAllChangesOnSuccess);
/// <summary>
/// 保存到数据库
/// </summary>
/// <param name="cancellationToken">是否等待任务完成时要观察</param>
/// <returns></returns>
Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);
/// <summary>
/// 保存到数据库
/// </summary>
/// <param name="acceptAllChangesOnSuccess">是否更改成功发送到数据库后是否调用AcceptAllChanges()</param>
/// <param name="cancellationToken">是否等待任务完成时要观察</param>
/// <returns></returns>
Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess,
CancellationToken cancellationToken = default);
/// <summary>
/// 根据sql语句返回DataTable数据
/// </summary>
/// <param name="sql">Sql语句</param>
/// <param name="cmdTimeout">执行超时时间,默认30毫秒</param>
/// <param name="parameters">DbParameter[]参数</param>
/// <returns></returns>
DataTable GetDataTable(string sql, int cmdTimeout = 30, params DbParameter[] parameters);
/// <summary>
/// 根据sql语句返回List集合数据
/// </summary>
/// <param name="sql">Sql语句</param>
/// <param name="cmdTimeout">执行超时时间,默认30毫秒</param>
/// <param name="parameters">DbParameter[]参数</param>
/// <returns></returns>
List<DataTable> GetDataTables(string sql, int cmdTimeout = 30, params DbParameter[] parameters);
#region 新增
/// <summary>
/// 新增实体
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entity"></param>
/// <returns></returns>
int Add<T>(T entity) where T : class;
/// <summary>
/// 异步新增
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entity"></param>
/// <returns></returns>
Task<int> AddAsync<T>(T entity) where T : class;
/// <summary>
/// 批量新增
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entities"></param>
/// <returns></returns>
int AddRange<T>(ICollection<T> entities) where T : class;
/// <summary>
/// 异步批量新增
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entities"></param>
/// <returns></returns>
Task<int> AddRangeAsync<T>(ICollection<T> entities) where T : class;
#endregion 新增
#region 更新
/// <summary>
/// 更新保存实体
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entity"></param>
/// <returns></returns>
int Edit<T>(T entity) where T : class;
/// <summary>
/// 批量更新保存实体
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entities"></param>
/// <returns></returns>
int EditRange<T>(ICollection<T> entities) where T : class;
/// <summary>
/// 更新指定字段的值
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="model">数据实体</param>
/// <param name="updateColumns">指定字段</param>
/// <returns></returns>
int Update<T>(T model, params string[] updateColumns) where T : class;
/// <summary>
/// 按条件更新,
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="where">条件</param>
/// <param name="updateFactory"></param>
/// <returns></returns>
//int Update<T>(Expression<Func<T, bool>> @where, Expression<Func<T, T>> updateFactory) where T : class;
/// <summary>
/// 按条件更新,
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="where">条件</param>
/// <param name="updateFactory"></param>
/// <returns></returns>
// Task<int> UpdateAsync<T>(Expression<Func<T, bool>> @where, Expression<Func<T, T>> updateFactory)
// where T : class;
#endregion 更新
#region 查询
/// <summary>
/// 根据条件统计数量Count()
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="where">查询条件</param>
/// <returns></returns>
int Count<T>(Expression<Func<T, bool>> where = null) where T : class;
/// <summary>
/// 根据条件异步统计数量Count()
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="where">查询条件</param>
/// <returns></returns>
Task<int> CountAsync<T>(Expression<Func<T, bool>> where = null) where T : class;
/// <summary>
/// 是否存在,存在返回true,不存在返回false
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="where">查询条件</param>
/// <returns></returns>
bool Exist<T>(Expression<Func<T, bool>> where = null) where T : class;
/// <summary>
/// 是否存在,存在返回true,不存在返回false
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="where">查询条件</param>
/// <returns></returns>
Task<bool> ExistAsync<T>(Expression<Func<T, bool>> where = null) where T : class;
/// <summary>
/// 根据条件进行查询数据
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="include"></param>
/// <param name="where">查询数据</param>
/// <returns></returns>
IQueryable<T> FilterWithInclude<T>(Func<IQueryable<T>, IQueryable<T>> include, Expression<Func<T, bool>> where)
where T : class;
/// <summary>
/// 根据主键查询实体
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key">主键值</param>
/// <returns></returns>
T Find<T>(object key) where T : class;
/// <summary>
/// 根据主键查询实体
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key">主键值</param>
/// <returns></returns>
T Find<T>(string key) where T : class;
/// <summary>
/// 根据主键查询实体
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TKey">主键类型</typeparam>
/// <param name="key">主键值</param>
/// <returns></returns>
T Find<T, TKey>(TKey key) where T : Entity;
/// <summary>
/// 根据主键查询实体
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key">主键值</param>
/// <returns></returns>
Task<T> FindAsync<T>(object key) where T : class;
/// <summary>
/// 根据主键查询实体
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TKey">主键类型</typeparam>
/// <param name="key">主键值</param>
/// <returns></returns>
Task<T> FindAsync<T, TKey>(TKey key) where T : Entity;
/// <summary>
/// 根据条件查询实体,返回实体集合
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="where">查询条件</param>
/// <param name="asNoTracking">是否启用模型跟踪,默认为false不跟踪</param>
/// <returns></returns>
IQueryable<T> Get<T>(Expression<Func<T, bool>> where = null, bool asNoTracking = false) where T : class;
/// <summary>
/// 获取所有实体类型
/// </summary>
/// <returns></returns>
List<IEntityType> GetAllEntityTypes();
/// <summary>
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
DbSet<T> GetDbSet<T>() where T : class;
/// <summary>
/// 根据条件查询一个实体,
/// 检验序列中是否包含有元素。引用类型的默认值default(T)为null,表示在序列中没有找到元素。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="where">查询条件</param>
/// <returns></returns>
T GetSingleOrDefault<T>(Expression<Func<T, bool>> where = null) where T : class;
/// <summary>
/// 根据条件查询一个实体,
/// 检验序列中是否包含有元素。引用类型的默认值default(T)为null,表示在序列中没有找到元素。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="where">查询条件</param>
/// <returns></returns>
Task<T> GetSingleOrDefaultAsync<T>(Expression<Func<T, bool>> where = null) where T : class;
/// <summary>
/// 根据条件查询一个实体,
/// 异步返回序列的第一个元素,如果序列不包含元素,则返回默认值。
/// 引用类型的默认值default(T)为null,表示在序列中没有找到元素。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="where">查询条件</param>
/// <returns></returns>
Task<T> GetFirstOrDefaultAsync<T>(Expression<Func<T, bool>> where = null) where T : class;
#endregion 查询
#region 显式编译的查询,提高查询性能
/// <summary>
/// 根据主键查询返回一个实体,该方法是显式编译的查询
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TKey">主键类型</typeparam>
/// <param name="id">主键值</param>
/// <returns></returns>
T GetByCompileQuery<T, TKey>(TKey id) where T : Entity;
/// <summary>
/// 根据主键查询返回一个实体,该方法是显式编译的查询
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TKey">主键类型</typeparam>
/// <param name="id">主键值</param>
/// <returns></returns>
Task<T> GetByCompileQueryAsync<T, TKey>(TKey id) where T : Entity;
/// <summary>
/// 根据条件查询返回实体集合,该方法是显式编译的查询
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="filter">查询条件</param>
/// <returns></returns>
IList<T> GetByCompileQuery<T>(Expression<Func<T, bool>> filter) where T : class;
/// <summary>
/// 根据条件查询返回实体集合,该方法是显式编译的查询
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="filter">查询条件</param>
/// <returns></returns>
Task<List<T>> GetByCompileQueryAsync<T>(Expression<Func<T, bool>> filter) where T : class;
/// <summary>
/// 根据条件查询一个实体,该方法是显式编译的查询
/// 检验序列中是否包含有元素。引用类型的默认值default(T)为null,表示在序列中没有找到元素。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="filter">查询条件</param>
/// <returns></returns>
T FirstOrDefaultByCompileQuery<T>(Expression<Func<T, bool>> filter) where T : class;
/// <summary>
/// 根据条件查询一个实体,该方法是显式编译的查询
/// 检验序列中是否包含有元素。引用类型的默认值default(T)为null,表示在序列中没有找到元素。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="filter">查询条件</param>
/// <returns></returns>
Task<T> FirstOrDefaultByCompileQueryAsync<T>(Expression<Func<T, bool>> filter) where T : class;
/// <summary>
/// 根据条件查询一个实体,启用模型跟踪,该方法是显式编译的查询
/// 检验序列中是否包含有元素。引用类型的默认值default(T)为null,表示在序列中没有找到元素。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="filter">查询条件</param>
/// <returns></returns>
T FirstOrDefaultWithTrackingByCompileQuery<T>(Expression<Func<T, bool>> filter) where T : class;
/// <summary>
/// 根据条件查询一个实体,启用模型跟踪,该方法是显式编译的查询
/// 检验序列中是否包含有元素。引用类型的默认值default(T)为null,表示在序列中没有找到元素。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="filter">查询条件</param>
/// <returns></returns>
Task<T> FirstOrDefaultWithTrackingByCompileQueryAsync<T>(Expression<Func<T, bool>> filter) where T : class;
/// <summary>
/// 统计数量Count(),该方法是显式编译的查询
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="filter">查询条件</param>
/// <returns></returns>
int CountByCompileQuery<T>(Expression<Func<T, bool>> filter) where T : class;
/// <summary>
/// 统计数量Count(),该方法是显式编译的查询
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="filter">查询条件</param>
/// <returns></returns>
Task<int> CountByCompileQueryAsync<T>(Expression<Func<T, bool>> filter) where T : class;
#endregion 显式编译的查询,提高查询性能
}
}

24
Znyc.Cloudcar.Admin.Commons/Core/IDbContext/IDbContextFactory.cs

@ -0,0 +1,24 @@
using Znyc.Cloudcar.Admin.Commons.DataManager;
using Znyc.Cloudcar.Admin.Commons.DbContextCore;
namespace Znyc.Cloudcar.Admin.Commons.IDbContext
{
/// <summary>
/// </summary>
public interface IDbContextFactory
{
/// <summary>
/// </summary>
/// <param name="writeAndRead">指定读、写操作</param>
/// <returns></returns>
BaseDbContext CreateContext(WriteAndReadEnum writeAndRead);
/// <summary>
/// 创建数据库读写上下文
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="writeAndRead">指定读、写操作</param>
/// <returns></returns>
BaseDbContext CreateContext<TEntity>(WriteAndReadEnum writeAndRead);
}
}

6
Znyc.Cloudcar.Admin.Commons/Core/IDbContext/IMySqlDbContext.cs

@ -0,0 +1,6 @@
namespace Znyc.Cloudcar.Admin.Commons.IDbContext
{
public interface IMySqlDbContext : IDbContextCore
{
}
}

6
Znyc.Cloudcar.Admin.Commons/Core/IDbContext/IOracleDbContext.cs

@ -0,0 +1,6 @@
namespace Znyc.Cloudcar.Admin.Commons.IDbContext
{
public interface IOracleDbContext : IDbContextCore
{
}
}

6
Znyc.Cloudcar.Admin.Commons/Core/IDbContext/IPostgreSQLDbContext.cs

@ -0,0 +1,6 @@
namespace Znyc.Cloudcar.Admin.Commons.IDbContext
{
public interface IPostgreSQLDbContext : IDbContextCore
{
}
}

6
Znyc.Cloudcar.Admin.Commons/Core/IDbContext/ISQLiteDbContext.cs

@ -0,0 +1,6 @@
namespace Znyc.Cloudcar.Admin.Commons.IDbContext
{
public interface ISQLiteDbContext : IDbContextCore
{
}
}

6
Znyc.Cloudcar.Admin.Commons/Core/IDbContext/ISqlServerDbContext.cs

@ -0,0 +1,6 @@
namespace Znyc.Cloudcar.Admin.Commons.IDbContext
{
public interface ISqlServerDbContext : IDbContextCore
{
}
}

14
Znyc.Cloudcar.Admin.Commons/Core/IRepositories/IReadOnlyRepository.cs

@ -0,0 +1,14 @@
using System;
using Znyc.Cloudcar.Admin.Commons.Entitys;
namespace Znyc.Cloudcar.Admin.Commons.Core.IRepositories
{
/// <summary>
/// 只读仓储接口,提供查询相关方法
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TKey"></typeparam>
public interface IReadOnlyRepository<T, TKey> : IDisposable where T : Entity
{
}
}

833
Znyc.Cloudcar.Admin.Commons/Core/IRepositories/IRepository.cs

@ -0,0 +1,833 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq.Expressions;
using System.Threading.Tasks;
using Znyc.Cloudcar.Admin.Commons.Entitys;
using Znyc.Cloudcar.Admin.Commons.Pages;
namespace Znyc.Cloudcar.Admin.Commons.IRepositories
{
/// <summary>
/// 定义泛型接口,实体仓储模型的数据标准操作
/// </summary>
/// <typeparam name="T">实体类型</typeparam>
/// <typeparam name="TKey">主键类型</typeparam>
public interface IRepository<T, TKey> : IDisposable where T : Entity
{
#region dapper 操作
#region 新增
/// <summary>
/// 同步新增实体。
/// </summary>
/// <param name="entity">实体</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
long Insert(T entity, IDbTransaction trans = null);
/// <summary>
/// 异步新增实体。
/// </summary>
/// <param name="entity">实体</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
Task<int> InsertAsync(T entity, IDbTransaction trans = null);
/// <summary>
/// 异步新增实体返回主键
/// </summary>
/// <param name="entity"></param>
/// <param name="trans"></param>
/// <returns></returns>
Task<long> InsertReturnPrimaryKeyAsync(T entity, IDbTransaction trans = null);
/// <summary>
/// 同步批量新增实体。
/// </summary>
/// <param name="entities">实体集合</param>
/// <returns></returns>
void Insert(List<T> entities);
#endregion 新增
#region 删除
/// <summary>
/// 同步物理删除实体。
/// </summary>
/// <param name="entity">实体</param>
/// <returns></returns>
bool Delete(T entity);
/// <summary>
/// 异步物理删除实体。
/// </summary>
/// <param name="entity">实体</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
Task<bool> DeleteAsync(T entity, IDbTransaction trans = null);
/// <summary>
/// 同步物理删除实体。
/// </summary>
/// <param name="primaryKey">主键</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
bool Delete(TKey primaryKey, IDbTransaction trans = null);
/// <summary>
/// 异步物理删除实体。
/// </summary>
/// <param name="primaryKey">主键</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
Task<bool> DeleteAsync(TKey primaryKey, IDbTransaction trans = null);
/// <summary>
/// 按主键批量删除
/// </summary>
/// <param name="ids"></param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
bool DeleteBatch(IList<dynamic> ids, IDbTransaction trans = null);
/// <summary>
/// 按条件批量删除
/// </summary>
/// <param name="where">条件</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
bool DeleteBatchWhere(string where, IDbTransaction trans = null);
/// <summary>
/// 异步按条件批量删除
/// </summary>
/// <param name="where">条件</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
Task<bool> DeleteBatchWhereAsync(string where, IDbTransaction trans = null);
#endregion 删除
#region 更新操作
#region 更新实体或批量更新
/// <summary>
/// 同步更新实体。
/// </summary>
/// <param name="entity">实体</param>
/// <param name="primaryKey">主键ID</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
bool Update(T entity, TKey primaryKey, IDbTransaction trans = null);
/// <summary>
/// 异步更新实体。
/// </summary>
/// <param name="entity">实体</param>
/// <param name="primaryKey">主键ID</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
Task<bool> UpdateAsync(T entity, TKey primaryKey, IDbTransaction trans = null);
#endregion 更新实体或批量更新
#region 更新某一字段值
/// <summary>
/// 更新某一字段值
/// </summary>
/// <param name="strField">字段</param>
/// <param name="fieldValue">字段值</param>
/// <param name="where">条件,为空更新所有内容</param>
/// <param name="trans"></param>
/// <returns></returns>
bool UpdateTableField(string strField, string fieldValue, string where, IDbTransaction trans = null);
/// <summary>
/// 异步更新某一字段值
/// </summary>
/// <param name="strField">字段</param>
/// <param name="fieldValue">字段值</param>
/// <param name="where">条件,为空更新所有内容</param>
/// <param name="trans"></param>
/// <returns></returns>
Task<bool> UpdateTableFieldAsync(string strField, string fieldValue, string where, IDbTransaction trans = null);
/// <summary>
/// 更新某一字段值,字段值为数字
/// </summary>
/// <param name="strField">字段</param>
/// <param name="fieldValue">字段值数字</param>
/// <param name="where">条件,为空更新所有内容</param>
/// <param name="trans">事务对象</param>
/// <returns>执行成功返回<c>true</c>,否则为<c>false</c>。</returns>
bool UpdateTableField(string strField, int fieldValue, string where, IDbTransaction trans = null);
/// <summary>
/// 更新某一字段值,字段值为数字
/// </summary>
/// <param name="strField">字段</param>
/// <param name="fieldValue">字段值数字</param>
/// <param name="where">条件,为空更新所有内容</param>
/// <param name="trans">事务对象</param>
/// <returns>执行成功返回<c>true</c>,否则为<c>false</c>。</returns>
Task<bool> UpdateTableFieldAsync(string strField, int fieldValue, string where, IDbTransaction trans = null);
#endregion 更新某一字段值
#region 逻辑删除
/// <summary>
/// 同步软删除信息,将IsDeleted设置为1-删除,0-恢复删除
/// </summary>
/// <param name="bl">true为不删除,false删除</param>
/// <param name="primaryKey">主键ID</param>
/// <param name="userId">操作用户</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
bool DeleteSoft(bool bl, TKey primaryKey, long userId = 0, IDbTransaction trans = null);
/// <summary>
/// 异步软删除信息,将IsDeleted设置为1-删除,0-恢复删除
/// </summary>
/// <param name="bl">true为不删除,false删除</param>
/// c
/// <param name="primaryKey">主键ID</param>
/// <param name="userId">操作用户</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
Task<bool> DeleteSoftAsync(bool bl, TKey primaryKey, long userId = 0, IDbTransaction trans = null);
/// <summary>
/// 异步批量软删除信息,将IsDeleted设置为1-删除,0-恢复删除
/// </summary>
/// <param name="bl">true为不删除,false删除</param>
/// c
/// <param name="where">条件</param>
/// <param name="userId">操作用户</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
Task<bool> DeleteSoftBatchAsync(bool bl, string where, long userId = 0, IDbTransaction trans = null);
#endregion 逻辑删除
#region 数据有效性
/// <summary>
/// 设置数据有效性,将IsEnabled设置为1-有效,0-为无效
/// </summary>
/// <param name="bl">true为有效,false无效</param>
/// <param name="primaryKey">主键ID</param>
/// <param name="userId">操作用户</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
bool SetEnabledMark(bool bl, TKey primaryKey, long userId = 0, IDbTransaction trans = null);
/// <summary>
/// 异步设置数据有效性,将IsEnabled设置为1:有效,0-为无效
/// </summary>
/// <param name="bl">true为有效,false无效</param>
/// <param name="primaryKey">主键ID</param>
/// <param name="userId">操作用户</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
Task<bool> SetEnabledMarkAsync(bool bl, TKey primaryKey, long userId = 0, IDbTransaction trans = null);
/// <summary>
/// 异步按条件设置数据有效性,将IsEnabled设置为1:有效,0-为无效
/// </summary>
/// <param name="bl">true为有效,false无效</param>
/// <param name="where">条件</param>
/// <param name="userId">操作用户</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
Task<bool> SetEnabledMarkByWhereAsync(bool bl, string where, long userId = 0, IDbTransaction trans = null);
/// <summary>
/// 异步按条件设置数据的状态,将State设置为0:审核中,1:正常,-1:停用,-2:停用
/// </summary>
/// <param name="bl">0:审核中,1:正常,-1:停用,-2:停用</param>
/// <param name="where">条件</param>
/// <param name="userId">操作用户</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
Task<bool> SetStatusByWhereAsync(int bl, string where, long userId = 0, IDbTransaction trans = null);
/// <summary>
/// 异步按条件设置数据有效性,将IsEnabled设置为1:有效,0-为无效
/// </summary>
/// <param name="bl">true为有效,false无效</param>
/// <param name="where">条件</param>
/// <param name="paramparameters">参数</param>
/// <param name="userId">操作用户</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
Task<bool> SetEnabledMarkByWhereAsync(bool bl, string where, object paramparameters = null, long userId = 0,
IDbTransaction trans = null);
#endregion 数据有效性
#endregion 更新操作
#region 查询
#region 单个实体
/// <summary>
/// 同步查询单个实体。
/// </summary>
/// <param name="primaryKey">主键</param>
/// <returns></returns>
T Get(TKey primaryKey);
/// <summary>
/// 异步查询单个实体。
/// </summary>
/// <param name="primaryKey">主键</param>
/// <returns></returns>
Task<T> GetAsync(TKey primaryKey);
/// <summary>
/// 同步查询单个实体。
/// </summary>
/// <param name="where">查询条件</param>
/// <returns></returns>
T GetWhere(string where);
/// <summary>
/// 异步查询单个实体。
/// </summary>
/// <param name="where">查询条件</param>
/// <returns></returns>
Task<T> GetWhereAsync(string where);
#endregion 单个实体
/// <summary>
/// 获取所有数据,谨慎使用
/// </summary>
/// <param name="trans">事务对象</param>
/// <returns></returns>
IEnumerable<T> GetAll(IDbTransaction trans = null);
/// <summary>
/// 获取所有数据,谨慎使用
/// </summary>
/// <param name="trans">事务对象</param>
/// <returns></returns>
Task<IEnumerable<T>> GetAllAsync(IDbTransaction trans = null);
/// <summary>
/// 根据查询条件查询数据
/// </summary>
/// <param name="where">查询条件</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
IEnumerable<T> GetListWhere(string where = null, IDbTransaction trans = null);
/// <summary>
/// 异步根据查询条件查询数据
/// </summary>
/// <param name="where">查询条件</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
Task<IEnumerable<T>> GetListWhereAsync(string where = null, IDbTransaction trans = null);
/// <summary>
/// 根据查询条件查询前多少条数据
/// </summary>
/// <param name="top">多少条数据</param>
/// <param name="where">查询条件</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
IEnumerable<T> GetListTopWhere(int top, string where = null, IDbTransaction trans = null);
/// <summary>
/// 根据查询条件查询前多少条数据
/// </summary>
/// <param name="top">多少条数据</param>
/// <param name="where">查询条件</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
Task<IEnumerable<T>> GetListTopWhereAsync(int top, string where = null, IDbTransaction trans = null);
/// <summary>
/// 查询软删除的数据,如果查询条件为空,即查询所有软删除的数据
/// </summary>
/// <param name="where">查询条件</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
IEnumerable<T> GetAllByIsIsDeleted(string where = null, IDbTransaction trans = null);
/// <summary>
/// 查询未软删除的数据,如果查询条件为空,即查询所有未软删除的数据
/// </summary>
/// <param name="where">查询条件</param>
/// <param name="tran">事务对象</param>
/// <returns></returns>
IEnumerable<T> GetAllByIsNotIsDeleted(string where = null, IDbTransaction tran = null);
/// <summary>
/// 查询有效的数据,如果查询条件为空,即查询所有有效的数据
/// </summary>
/// <param name="where">查询条件</param>
/// <param name="tran">事务对象</param>
/// <returns></returns>
IEnumerable<T> GetAllByIsEnabledMark(string where = null, IDbTransaction tran = null);
/// <summary>
/// 查询无效的数据,如果查询条件为空,即查询所有无效的数据
/// </summary>
/// <param name="where">查询条件</param>
/// <param name="tran">事务对象</param>
/// <returns></returns>
IEnumerable<T> GetAllByIsNotEnabledMark(string where = null, IDbTransaction tran = null);
/// <summary>
/// 查询未软删除且有效的数据,如果查询条件为空,即查询所有数据
/// </summary>
/// <param name="where">查询条件</param>
/// <param name="tran">事务对象</param>
/// <returns></returns>
IEnumerable<T> GetAllByIsNotDeleteAndEnabledMark(string where = null, IDbTransaction tran = null);
/// <summary>
/// 查询软删除的数据,如果查询条件为空,即查询所有软删除的数据
/// </summary>
/// <param name="where">查询条件</param>
/// <param name="tran">事务对象</param>
/// <returns></returns>
Task<IEnumerable<T>> GetAllByIsIsDeletedAsync(string where = null, IDbTransaction tran = null);
/// <summary>
/// 查询未软删除的数据,如果查询条件为空,即查询所有未软删除的数据
/// </summary>
/// <param name="where">查询条件</param>
/// <param name="tran">事务对象</param>
/// <returns></returns>
Task<IEnumerable<T>> GetAllByIsNotIsDeletedAsync(string where = null, IDbTransaction tran = null);
/// <summary>
/// 查询有效的数据,如果查询条件为空,即查询所有有效的数据
/// </summary>
/// <param name="where">查询条件</param>
/// <param name="tran">事务对象</param>
/// <returns></returns>
Task<IEnumerable<T>> GetAllByIsEnabledMarkAsync(string where = null, IDbTransaction tran = null);
/// <summary>
/// 查询无效的数据,如果查询条件为空,即查询所有无效的数据
/// </summary>
/// <param name="where">查询条件</param>
/// <param name="tran">事务对象</param>
/// <returns></returns>
Task<IEnumerable<T>> GetAllByIsNotEnabledMarkAsync(string where = null, IDbTransaction tran = null);
/// <summary>
/// 查询未软删除且有效的数据,如果查询条件为空,即查询所有数据
/// </summary>
/// <param name="where">查询条件</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
Task<IEnumerable<T>> GetAllByIsNotDeleteAndEnabledMarkAsync(string where = null, IDbTransaction trans = null);
/// <summary>
/// 根据条件查询数据库,并返回对象集合(用于分页数据显示)
/// </summary>
/// <param name="condition">查询的条件</param>
/// <param name="info">分页实体</param>
/// <param name="fieldToSort">排序字段</param>
/// <param name="desc">是否降序</param>
/// <param name="trans">事务对象</param>
/// <returns>指定对象的集合</returns>
Task<List<T>> FindWithPagerAsync(string condition, PagerInfo info, string fieldToSort, bool desc,
IDbTransaction trans = null);
/// <summary>
/// 根据条件查询数据库,并返回对象集合(用于分页数据显示)
/// </summary>
/// <param name="condition">查询的条件</param>
/// <param name="info">分页实体</param>
/// <param name="fieldToSort">排序字段</param>
/// <param name="desc">是否降序</param>
/// <param name="trans">事务对象</param>
/// <returns>指定对象的集合</returns>
List<T> FindWithPager(string condition, PagerInfo info, string fieldToSort, bool desc,
IDbTransaction trans = null);
/// <summary>
/// 根据条件查询数据库,并返回对象集合(用于分页数据显示)
/// </summary>
/// <param name="condition">查询的条件</param>
/// <param name="info">分页实体</param>
/// <param name="fieldToSort">排序字段</param>
/// <param name="trans">事务对象</param>
/// <returns>指定对象的集合</returns>
Task<List<T>> FindWithPagerAsync(string condition, PagerInfo info, string fieldToSort,
IDbTransaction trans = null);
/// <summary>
/// 根据条件查询数据库,并返回对象集合(用于分页数据显示)
/// </summary>
/// <param name="condition">查询的条件</param>
/// <param name="info">分页实体</param>
/// <param name="fieldToSort">排序字段</param>
/// <param name="trans">事务对象</param>
/// <returns>指定对象的集合</returns>
List<T> FindWithPager(string condition, PagerInfo info, string fieldToSort, IDbTransaction trans = null);
/// <summary>
/// 根据条件查询数据库,并返回对象集合(用于分页数据显示)
/// </summary>
/// <param name="condition">查询的条件</param>
/// <param name="info">分页实体</param>
/// <param name="trans">事务对象</param>
/// <returns>指定对象的集合</returns>
Task<List<T>> FindWithPagerAsync(string condition, PagerInfo info, IDbTransaction trans = null);
/// <summary>
/// 根据条件查询数据库,并返回对象集合(用于分页数据显示)
/// </summary>
/// <param name="condition">查询的条件</param>
/// <param name="info">分页实体</param>
/// <param name="trans">事务对象</param>
/// <returns>指定对象的集合</returns>
List<T> FindWithPager(string condition, PagerInfo info, IDbTransaction trans = null);
/// <summary>
/// 分页查询,自行封装sql语句(仅支持sql server)
/// 非常复杂的查询,可在具体业务模块重写该方法
/// </summary>
/// <param name="condition">查询条件</param>
/// <param name="info">分页信息</param>
/// <param name="fieldToSort">排序字段</param>
/// <param name="desc">排序方式 true为desc,false为asc</param>
/// <param name="trans"></param>
/// <returns></returns>
Task<List<T>> FindWithPagerSqlAsync(string condition, PagerInfo info, string fieldToSort, bool desc,
IDbTransaction trans = null);
/// <summary>
/// 分页查询,自行封装sql语句(仅支持sql server)
/// 非常复杂的查询,可在具体业务模块重写该方法
/// </summary>
/// <param name="condition">查询条件</param>
/// <param name="info">分页信息</param>
/// <param name="fieldToSort">排序字段</param>
/// <param name="desc">排序方式 true为desc,false为asc</param>
/// <param name="trans"></param>
/// <returns></returns>
List<T> FindWithPagerSql(string condition, PagerInfo info, string fieldToSort, bool desc,
IDbTransaction trans = null);
/// <summary>
/// 分页查询包含用户信息(仅支持sql server)
/// 查询主表别名为t1,用户表别名为t2,在查询字段需要注意使用t1.xxx格式,xx表示主表字段
/// 用户信息主要有用户账号:Account、昵称:UserName、真实姓名:RealName、头像:HeadIcon、手机号:MobilePhone
/// 输出对象请在Dtos中进行自行封装,不能是使用实体Model类
/// </summary>
/// <param name="condition">查询条件字段需要加表别名</param>
/// <param name="info">分页信息</param>
/// <param name="fieldToSort">排序字段,也需要加表别名</param>
/// <param name="desc">排序方式</param>
/// <param name="trans">事务</param>
/// <returns></returns>
Task<List<object>> FindWithPagerRelationUserAsync(string condition, PagerInfo info, string fieldToSort,
bool desc, IDbTransaction trans = null);
/// <summary>
/// 分页查询包含用户信息(仅支持sql server)
/// 查询主表别名为t1,用户表别名为t2,在查询字段需要注意使用t1.xxx格式,xx表示主表字段
/// 用户信息主要有用户账号:Account、昵称:UserName、真实姓名:RealName、头像:HeadIcon、手机号:MobilePhone
/// 输出对象请在Dtos中进行自行封装,不能是使用实体Model类
/// </summary>
/// <param name="condition">查询条件字段需要加表别名</param>
/// <param name="info">分页信息</param>
/// <param name="fieldToSort">排序字段,也需要加表别名</param>
/// <param name="desc">排序方式</param>
/// <param name="trans">事务</param>
/// <returns></returns>
List<object> FindWithPagerRelationUser(string condition, PagerInfo info, string fieldToSort, bool desc,
IDbTransaction trans = null);
/// <summary>
/// 根据条件统计数据
/// </summary>
/// <param name="condition">查询条件</param>
/// <param name="fieldName">统计字段名称</param>
/// <returns></returns>
int GetCountByWhere(string condition, string fieldName = "*");
/// <summary>
/// 根据条件统计数据
/// </summary>
/// <param name="condition">查询条件</param>
/// <param name="fieldName">统计字段名称</param>
/// <returns></returns>
Task<int> GetCountByWhereAsync(string condition, string fieldName = "*");
/// <summary>
/// /
/// </summary>
/// <returns></returns>
Task<int> GetCount();
/// <summary>
/// 根据条件查询获取某个字段的最大值
/// </summary>
/// <param name="strField">字段</param>
/// <param name="where">条件</param>
/// <param name="trans">事务</param>
/// <returns>返回字段的最大值</returns>
Task<dynamic> GetMaxValueByFieldAsync(string strField, string where, IDbTransaction trans = null);
/// <summary>
/// 根据条件统计某个字段之和,sum(字段)
/// </summary>
/// <param name="strField">字段</param>
/// <param name="where">条件</param>
/// <param name="trans">事务</param>
/// <returns>返回字段求和后的值</returns>
Task<dynamic> GetSumValueByFieldAsync(string strField, string where, IDbTransaction trans = null);
#endregion 查询
#region 多表批量操作,支持事务
/// <summary>
/// 多表操作--事务
/// </summary>
/// <param name="trans">事务</param>
/// <param name="commandTimeout">超时</param>
/// <returns></returns>
Task<Tuple<bool, string>>
ExecuteTransactionAsync(List<Tuple<string, object>> trans, int? commandTimeout = null);
/// <summary>
/// 多表操作--事务
/// </summary>
/// <param name="trans">事务</param>
/// <param name="commandTimeout">超时</param>
/// <returns></returns>
Tuple<bool, string> ExecuteTransaction(List<Tuple<string, object>> trans, int? commandTimeout = null);
#endregion 多表批量操作,支持事务
#endregion dapper 操作
#region EF 操作
#region Insert 新增
/// <summary>
/// 新增实体
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
int Add(T entity);
/// <summary>
/// 新增实体
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
Task<int> AddAsync(T entity);
/// <summary>
/// 批量新增,数量量较多是推荐使用BulkInsert()
/// </summary>
/// <param name="entities"></param>
/// <returns></returns>
int AddRange(ICollection<T> entities);
/// <summary>
/// 批量新增,数量量较多是推荐使用BulkInsert()
/// </summary>
/// <param name="entities"></param>
/// <returns></returns>
Task<int> AddRangeAsync(ICollection<T> entities);
/// <summary>
/// 批量新增SqlBulk方式,效率最高
/// </summary>
/// <param name="entities"></param>
/// <param name="destinationTableName"></param>
void BulkInsert(IList<T> entities, string destinationTableName = null);
/// <summary>
/// 执行新增的sql语句
/// </summary>
/// <param name="sql">新增Sql语句</param>
/// <returns></returns>
int AddBySql(string sql);
#endregion Insert 新增
#region Delete 删除
/// <summary>
/// 根据主键删除数据
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
int Delete(TKey key);
/// <summary>
/// 执行删除数据Sql语句
/// </summary>
/// <param name="sql">删除的Sql语句</param>
/// <returns></returns>
int DeleteBySql(string sql);
#endregion Delete 删除
#region Update 更新
/// <summary>
/// 更新一个实体数据
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
int Edit(T entity);
/// <summary>
/// 批量更新数据实体
/// </summary>
/// <param name="entities"></param>
/// <returns></returns>
int EditRange(ICollection<T> entities);
/// <summary>
/// 更新指定字段的值
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="model">数据实体</param>
/// <param name="updateColumns">指定字段</param>
/// <returns></returns>
int Update(T model, params string[] updateColumns);
/// <summary>
/// 执行更新数据的Sql语句
/// </summary>
/// <param name="sql">更新数据的Sql语句</param>
/// <returns></returns>
int UpdateBySql(string sql);
#endregion Update 更新
#region Query 查询
/// <summary>
/// 根据条件统计数量Count()
/// </summary>
/// <param name="where"></param>
/// <returns></returns>
int Count(Expression<Func<T, bool>> where = null);
/// <summary>
/// 根据条件统计数量Count()
/// </summary>
/// <param name="where"></param>
/// <returns></returns>
Task<int> CountAsync(Expression<Func<T, bool>> where = null);
/// <summary>
/// 是否存在,存在返回true,不存在返回false
/// </summary>
/// <param name="where"></param>
/// <returns></returns>
bool Exist(Expression<Func<T, bool>> where = null);
/// <summary>
/// 是否存在,存在返回true,不存在返回false
/// </summary>
/// <param name="where"></param>
/// <returns></returns>
Task<bool> ExistAsync(Expression<Func<T, bool>> where = null);
/// <summary>
/// 根据主键获取实体。建议:如需使用Include和ThenInclude请重载此方法。
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
T GetSingle(TKey key);
/// <summary>
/// 根据主键获取实体。建议:如需使用Include和ThenInclude请重载此方法。
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
Task<T> GetSingleAsync(TKey key);
/// <summary>
/// 获取单个实体。建议:如需使用Include和ThenInclude请重载此方法。
/// </summary>
/// <param name="where"></param>
/// <returns></returns>
T GetSingleOrDefault(Expression<Func<T, bool>> where = null);
/// <summary>
/// 获取单个实体。建议:如需使用Include和ThenInclude请重载此方法。
/// </summary>
/// <param name="where"></param>
/// <returns></returns>
Task<T> GetSingleOrDefaultAsync(Expression<Func<T, bool>> where = null);
/// <summary>
/// 获取实体列表。建议:如需使用Include和ThenInclude请重载此方法。
/// </summary>
/// <param name="where"></param>
/// <returns></returns>
IList<T> Get(Expression<Func<T, bool>> where = null);
/// <summary>
/// 获取实体列表。建议:如需使用Include和ThenInclude请重载此方法。
/// </summary>
/// <param name="where"></param>
/// <returns></returns>
Task<List<T>> GetAsync(Expression<Func<T, bool>> where = null);
/// <summary>
/// 分页获取实体列表。建议:如需使用Include和ThenInclude请重载此方法。
/// </summary>
/// <param name="where">查询条件</param>
/// <param name="pagerInfo">分页信息</param>
/// <param name="asc">排序方式</param>
/// <param name="orderby">排序字段</param>
/// <returns></returns>
IEnumerable<T> GetByPagination(Expression<Func<T, bool>> where, PagerInfo pagerInfo, bool asc = true,
params Expression<Func<T, object>>[] orderby);
/// <summary>
/// sql语句查询数据集
/// </summary>
/// <param name="sql"></param>
/// <returns></returns>
List<T> GetBySql(string sql);
/// <summary>
/// sql语句查询数据集,返回输出Dto实体
/// </summary>
/// <typeparam name="TView">返回结果对象</typeparam>
/// <param name="sql"></param>
/// <returns></returns>
List<TView> GetViews<TView>(string sql);
/// <summary>
/// 查询视图
/// </summary>
/// <typeparam name="TView">返回结果对象</typeparam>
/// <param name="viewName">视图名称</param>
/// <param name="where">查询条件</param>
/// <returns></returns>
List<TView> GetViews<TView>(string viewName, Func<TView, bool> where);
#endregion Query 查询
#endregion EF 操作
}
}

629
Znyc.Cloudcar.Admin.Commons/Core/IServices/IService.cs

@ -0,0 +1,629 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Threading.Tasks;
using Znyc.Cloudcar.Admin.Commons.Dtos;
using Znyc.Cloudcar.Admin.Commons.Entitys;
using Znyc.Cloudcar.Admin.Commons.Pages;
namespace Znyc.Cloudcar.Admin.Commons.IServices
{
/// <summary>
/// 泛型应用服务接口
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TODto"></typeparam>
/// <typeparam name="TKey"></typeparam>
public interface IService<T, TODto, TKey> : IDisposable where T : Entity
where TODto : class
{
/// <summary>
/// 同步查询单个实体。
/// </summary>
/// <param name="id">主键</param>
/// <returns></returns>
T Get(TKey id);
/// <summary>
/// 同步查询单个实体。
/// </summary>
/// <param name="id">主键</param>
/// <returns></returns>
TODto GetOutDto(TKey id);
/// <summary>
/// 异步查询单个实体。
/// </summary>
/// <param name="id">主键</param>
/// <returns></returns>
Task<TODto> GetOutDtoAsync(TKey id);
/// <summary>
/// 异步查询单个实体。
/// </summary>
/// <param name="id">主键</param>
/// <returns></returns>
Task<T> GetAsync(TKey id);
/// <summary>
/// 同步查询单个实体。
/// </summary>
/// <param name="where">查询条件</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
T GetWhere(string where, IDbTransaction trans = null);
/// <summary>
/// 同步查询单个实体。
/// </summary>
/// <param name="where">查询条件</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
TODto GetOutDtoWhere(string where, IDbTransaction trans = null);
/// <summary>
/// 异步查询单个实体。
/// </summary>
/// <param name="where">查询条件</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
Task<T> GetWhereAsync(string where, IDbTransaction trans = null);
/// <summary>
/// 异步查询单个实体。
/// </summary>
/// <param name="where">查询条件</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
Task<TODto> GetOutDtoWhereAsync(string where, IDbTransaction trans = null);
/// <summary>
/// 同步查询所有实体。
/// </summary>
/// <param name="trans">事务对象</param>
/// <returns></returns>
IEnumerable<T> GetAll(IDbTransaction trans = null);
/// <summary>
/// 异步查询所有实体。
/// </summary>
/// <param name="trans">事务对象</param>
/// <returns></returns>
Task<IEnumerable<T>> GetAllAsync(IDbTransaction trans = null);
/// <summary>
/// 根据查询条件查询数据
/// </summary>
/// <param name="where">查询条件</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
IEnumerable<T> GetListWhere(string where = null, IDbTransaction trans = null);
/// <summary>
/// 异步根据查询条件查询数据
/// </summary>
/// <param name="where">查询条件</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
Task<IEnumerable<T>> GetListWhereAsync(string where = null, IDbTransaction trans = null);
/// <summary>
/// 根据查询条件查询前多少条数据
/// </summary>
/// <param name="top">多少条数据</param>
/// <param name="where">查询条件</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
IEnumerable<T> GetListTopWhere(int top, string where = null, IDbTransaction trans = null);
/// <summary>
/// 根据查询条件查询前多少条数据
/// </summary>
/// <param name="top">多少条数据</param>
/// <param name="where">查询条件</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
Task<IEnumerable<T>> GetListTopWhereAsync(int top, string where = null, IDbTransaction trans = null);
/// <summary>
/// 同步新增实体。
/// </summary>
/// <param name="entity">实体</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
long Insert(T entity, IDbTransaction trans = null);
/// <summary>
/// 异步新增实体。
/// </summary>
/// <param name="entity">实体</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
Task<int> InsertAsync(T entity, IDbTransaction trans = null);
/// <summary>
/// 异步新增实体返回主键
/// </summary>
/// <param name="entity"></param>
/// <param name="trans"></param>
/// <returns></returns>
Task<long> InsertReturnPrimaryKeyAsync(T entity, IDbTransaction trans = null);
/// <summary>
/// 同步批量新增实体。
/// </summary>
/// <param name="entities">实体集合</param>
/// <returns></returns>
void Insert(List<T> entities);
/// <summary>
/// 同步更新实体。
/// </summary>
/// <param name="entity">实体</param>
/// <param name="id">主键ID</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
bool Update(T entity, TKey id, IDbTransaction trans = null);
/// <summary>
/// 异步更新实体。
/// </summary>
/// <param name="entity">实体</param>
/// <param name="id">主键ID</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
Task<bool> UpdateAsync(T entity, TKey id, IDbTransaction trans = null);
/// <summary>
/// 更新某一字段值
/// </summary>
/// <param name="strField">字段</param>
/// <param name="fieldValue">字段值</param>
/// <param name="where">条件,为空更新所有内容</param>
/// <param name="trans"></param>
/// <returns></returns>
bool UpdateTableField(string strField, string fieldValue, string where, IDbTransaction trans = null);
/// <summary>
/// 异步更新某一字段值
/// </summary>
/// <param name="strField">字段</param>
/// <param name="fieldValue">字段值</param>
/// <param name="where">条件,为空更新所有内容</param>
/// <param name="trans"></param>
/// <returns></returns>
Task<bool> UpdateTableFieldAsync(string strField, string fieldValue, string where, IDbTransaction trans = null);
/// <summary>
/// 更新某一字段值,字段值为数字
/// </summary>
/// <param name="strField">字段</param>
/// <param name="fieldValue">字段值数字</param>
/// <param name="where">条件,为空更新所有内容</param>
/// <param name="trans">事务对象</param>
/// <returns>执行成功返回<c>true</c>,否则为<c>false</c>。</returns>
bool UpdateTableField(string strField, int fieldValue, string where, IDbTransaction trans = null);
/// <summary>
/// 更新某一字段值,字段值为数字
/// </summary>
/// <param name="strField">字段</param>
/// <param name="fieldValue">字段值数字</param>
/// <param name="where">条件,为空更新所有内容</param>
/// <param name="trans">事务对象</param>
/// <returns>执行成功返回<c>true</c>,否则为<c>false</c>。</returns>
Task<bool> UpdateTableFieldAsync(string strField, int fieldValue, string where, IDbTransaction trans = null);
/// <summary>
/// 同步物理删除实体。
/// </summary>
/// <param name="entity">实体</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
bool Delete(T entity, IDbTransaction trans = null);
/// <summary>
/// 异步物理删除实体。
/// </summary>
/// <param name="entity">实体</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
Task<bool> DeleteAsync(T entity, IDbTransaction trans = null);
/// <summary>
/// 同步物理删除实体。
/// </summary>
/// <param name="id">主键</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
bool Delete(TKey id, IDbTransaction trans = null);
/// <summary>
/// 异步物理删除实体。
/// </summary>
/// <param name="id">主键</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
Task<bool> DeleteAsync(TKey id, IDbTransaction trans = null);
/// <summary>
/// 按主键批量删除
/// </summary>
/// <param name="ids"></param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
bool DeleteBatch(IList<dynamic> ids, IDbTransaction trans = null);
/// <summary>
/// 按条件批量删除
/// </summary>
/// <param name="where">条件</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
bool DeleteBatchWhere(string where, IDbTransaction trans = null);
/// <summary>
/// 异步按条件批量删除
/// </summary>
/// <param name="where">条件</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
Task<bool> DeleteBatchWhereAsync(string where, IDbTransaction trans = null);
/// <summary>
/// 同步软删除信息,将IsDeleted设置为1-删除,0-恢复删除
/// </summary>
/// <param name="bl">true为不删除,false删除</param>
/// <param name="id">主键ID</param>
/// <param name="userId">操作用户</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
bool DeleteSoft(bool bl, TKey id, long userId = 0, IDbTransaction trans = null);
/// <summary>
/// 异步软删除信息,将IsDeleted设置为1-删除,0-恢复删除
/// </summary>
/// <param name="bl">true为不删除,false删除</param>
/// c
/// <param name="id">主键ID</param>
/// <param name="userId">操作用户</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
Task<bool> DeleteSoftAsync(bool bl, TKey id, long userId = 0, IDbTransaction trans = null);
/// <summary>
/// 异步批量软删除信息,将IsDeleted设置为1-删除,0-恢复删除
/// </summary>
/// <param name="bl">true为不删除,false删除</param>
/// c
/// <param name="where">条件</param>
/// <param name="userId">操作用户</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
Task<bool> DeleteSoftBatchAsync(bool bl, string where, long userId = 0, IDbTransaction trans = null);
/// <summary>
/// 设置数据有效性,将IsEnabled设置为1-有效,0-为无效
/// </summary>
/// <param name="bl">true为有效,false无效</param>
/// <param name="id">主键ID</param>
/// <param name="userId">操作用户</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
bool SetEnabledMark(bool bl, TKey id, long userId = 0, IDbTransaction trans = null);
/// <summary>
/// 异步设置数据有效性,将IsEnabled设置为1:有效,0-为无效
/// </summary>
/// <param name="bl">true为有效,false无效</param>
/// <param name="id">主键ID</param>
/// <param name="userId">操作用户</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
Task<bool> SetEnabledMarkAsync(bool bl, TKey id, long userId = 0, IDbTransaction trans = null);
/// <summary>
/// 异步按条件设置数据有效性,将IsEnabled设置为1:有效,0-为无效
/// </summary>
/// <param name="bl">true为有效,false无效</param>
/// <param name="where">条件</param>
/// <param name="userId">操作用户</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
Task<bool> SetEnabledMarkByWhereAsync(bool bl, string where, long userId = 0, IDbTransaction trans = null);
/// <summary>
/// 异步按条件设置数据的状态,将State设置为0:审核中,1:正常,-1:停用,-2:停用
/// </summary>
/// <param name="bl">0:审核中,1:正常,-1:停用,-2:停用</param>
/// <param name="where">条件</param>
/// <param name="userId">操作用户</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
Task<bool> SetStatusByWhereAsync(int bl, string where, long userId = 0,
IDbTransaction trans = null);
/// <summary>
/// 异步按条件设置数据有效性,将IsEnabled设置为1:有效,0-为无效
/// </summary>
/// <param name="bl">true为有效,false无效</param>
/// <param name="where">条件</param>
/// <param name="paramparameters"></param>
/// <param name="userId">操作用户</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
Task<bool> SetEnabledMarkByWhereAsync(bool bl, string where, object paramparameters = null, long userId = 0,
IDbTransaction trans = null);
/// <summary>
/// 查询软删除的数据,如果查询条件为空,即查询所有软删除的数据
/// </summary>
/// <param name="where">查询条件</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
IEnumerable<T> GetAllByIsIsDeleted(string where = null, IDbTransaction trans = null);
/// <summary>
/// 查询未软删除的数据,如果查询条件为空,即查询所有未软删除的数据
/// </summary>
/// <param name="where">查询条件</param>
/// <param name="tran">事务对象</param>
/// <returns></returns>
IEnumerable<T> GetAllByIsNotIsDeleted(string where = null, IDbTransaction tran = null);
/// <summary>
/// 查询有效的数据,如果查询条件为空,即查询所有有效的数据
/// </summary>
/// <param name="where">查询条件</param>
/// <param name="tran">事务对象</param>
/// <returns></returns>
IEnumerable<T> GetAllByIsEnabledMark(string where = null, IDbTransaction tran = null);
/// <summary>
/// 查询无效的数据,如果查询条件为空,即查询所有无效的数据
/// </summary>
/// <param name="where">查询条件</param>
/// <param name="tran">事务对象</param>
/// <returns></returns>
IEnumerable<T> GetAllByIsNotEnabledMark(string where = null, IDbTransaction tran = null);
/// <summary>
/// 查询未软删除且有效的数据,如果查询条件为空,即查询所有数据
/// </summary>
/// <param name="where">查询条件</param>
/// <param name="tran">事务对象</param>
/// <returns></returns>
IEnumerable<T> GetAllByIsNotDeleteAndEnabledMark(string where = null, IDbTransaction tran = null);
/// <summary>
/// 查询软删除的数据,如果查询条件为空,即查询所有软删除的数据
/// </summary>
/// <param name="where">查询条件</param>
/// <param name="tran">事务对象</param>
/// <returns></returns>
Task<IEnumerable<T>> GetAllByIsIsDeletedAsync(string where = null, IDbTransaction tran = null);
/// <summary>
/// 查询未软删除的数据,如果查询条件为空,即查询所有未软删除的数据
/// </summary>
/// <param name="where">查询条件</param>
/// <param name="tran">事务对象</param>
/// <returns></returns>
Task<IEnumerable<T>> GetAllByIsNotIsDeletedAsync(string where = null, IDbTransaction tran = null);
/// <summary>
/// 查询有效的数据,如果查询条件为空,即查询所有有效的数据
/// </summary>
/// <param name="where">查询条件</param>
/// <param name="tran">事务对象</param>
/// <returns></returns>
Task<IEnumerable<T>> GetAllByIsEnabledMarkAsync(string where = null, IDbTransaction tran = null);
/// <summary>
/// 查询无效的数据,如果查询条件为空,即查询所有无效的数据
/// </summary>
/// <param name="where">查询条件</param>
/// <param name="tran">事务对象</param>
/// <returns></returns>
Task<IEnumerable<T>> GetAllByIsNotEnabledMarkAsync(string where = null, IDbTransaction tran = null);
/// <summary>
/// 查询未软删除且有效的数据,如果查询条件为空,即查询所有数据
/// </summary>
/// <param name="where">查询条件</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
Task<IEnumerable<T>> GetAllByIsNotDeleteAndEnabledMarkAsync(string where = null, IDbTransaction trans = null);
/// <summary>
/// 根据条件查询数据库,并返回对象集合(用于分页数据显示)
/// </summary>
/// <param name="condition">查询的条件</param>
/// <param name="info">分页实体</param>
/// <param name="fieldToSort">排序字段</param>
/// <param name="desc">是否降序</param>
/// <param name="trans">事务对象</param>
/// <returns>指定对象的集合</returns>
Task<List<T>> FindWithPagerAsync(string condition, PagerInfo info, string fieldToSort, bool desc,
IDbTransaction trans = null);
/// <summary>
/// 根据条件查询数据库,并返回对象集合(用于分页数据显示)
/// </summary>
/// <param name="condition">查询的条件</param>
/// <param name="info">分页实体</param>
/// <param name="fieldToSort">排序字段</param>
/// <param name="desc">是否降序</param>
/// <param name="trans">事务对象</param>
/// <returns>指定对象的集合</returns>
List<T> FindWithPager(string condition, PagerInfo info, string fieldToSort, bool desc,
IDbTransaction trans = null);
/// <summary>
/// 根据条件查询数据库,并返回对象集合(用于分页数据显示)
/// </summary>
/// <param name="condition">查询的条件</param>
/// <param name="info">分页实体</param>
/// <param name="fieldToSort">排序字段</param>
/// <param name="trans">事务对象</param>
/// <returns>指定对象的集合</returns>
Task<List<T>> FindWithPagerAsync(string condition, PagerInfo info, string fieldToSort,
IDbTransaction trans = null);
/// <summary>
/// 根据条件查询数据库,并返回对象集合(用于分页数据显示)
/// </summary>
/// <param name="condition">查询的条件</param>
/// <param name="info">分页实体</param>
/// <param name="fieldToSort">排序字段</param>
/// <param name="trans">事务对象</param>
/// <returns>指定对象的集合</returns>
List<T> FindWithPager(string condition, PagerInfo info, string fieldToSort, IDbTransaction trans = null);
/// <summary>
/// 根据条件查询数据库,并返回对象集合(用于分页数据显示)
/// </summary>
/// <param name="condition">查询的条件</param>
/// <param name="info">分页实体</param>
/// <param name="trans">事务对象</param>
/// <returns>指定对象的集合</returns>
Task<List<T>> FindWithPagerAsync(string condition, PagerInfo info, IDbTransaction trans = null);
/// <summary>
/// 根据条件查询数据库,并返回对象集合(用于分页数据显示)
/// </summary>
/// <param name="condition">查询的条件</param>
/// <param name="info">分页实体</param>
/// <param name="trans">事务对象</param>
/// <returns>指定对象的集合</returns>
List<T> FindWithPager(string condition, PagerInfo info, IDbTransaction trans = null);
/// <summary>
/// 根据条件查询数据库,并返回对象集合(用于分页数据显示)
/// </summary>
/// <param name="search">查询的条件</param>
/// <returns>指定对象的集合</returns>
PageResult<TODto> FindWithPager(SearchInputDto<T> search);
/// <summary>
/// 根据条件查询数据库,并返回对象集合(用于分页数据显示)
/// </summary>
/// <param name="search">查询的条件</param>
/// <returns>指定对象的集合</returns>
Task<PageResult<TODto>> FindWithPagerAsync(SearchInputDto<T> search);
/// <summary>
/// 分页查询,自行封装sql语句(仅支持sql server)
/// 非常复杂的查询,可在具体业务模块重写该方法
/// </summary>
/// <param name="condition">查询条件</param>
/// <param name="info">分页信息</param>
/// <param name="fieldToSort">排序字段</param>
/// <param name="desc">排序方式 true为desc,false为asc</param>
/// <param name="trans"></param>
/// <returns></returns>
Task<List<T>> FindWithPagerSqlAsync(string condition, PagerInfo info, string fieldToSort, bool desc,
IDbTransaction trans = null);
/// <summary>
/// 分页查询,自行封装sql语句(仅支持sql server)
/// 非常复杂的查询,可在具体业务模块重写该方法
/// </summary>
/// <param name="condition">查询条件</param>
/// <param name="info">分页信息</param>
/// <param name="fieldToSort">排序字段</param>
/// <param name="desc">排序方式 true为desc,false为asc</param>
/// <param name="trans"></param>
/// <returns></returns>
List<T> FindWithPagerSql(string condition, PagerInfo info, string fieldToSort, bool desc,
IDbTransaction trans = null);
/// <summary>
/// 分页查询包含用户信息(仅支持sql server)
/// 查询主表别名为t1,用户表别名为t2,在查询字段需要注意使用t1.xxx格式,xx表示主表字段
/// 用户信息主要有用户账号:Account、昵称:UserName、真实姓名:RealName、头像:HeadIcon、手机号:MobilePhone
/// 输出对象请在Dtos中进行自行封装,不能是使用实体Model类
/// </summary>
/// <param name="condition">查询条件字段需要加表别名</param>
/// <param name="info">分页信息</param>
/// <param name="fieldToSort">排序字段,也需要加表别名</param>
/// <param name="desc">排序方式</param>
/// <param name="trans">事务</param>
/// <returns></returns>
Task<List<object>> FindWithPagerRelationUserAsync(string condition, PagerInfo info, string fieldToSort,
bool desc, IDbTransaction trans = null);
/// <summary>
/// 分页查询包含用户信息(仅支持sql server)
/// 查询主表别名为t1,用户表别名为t2,在查询字段需要注意使用t1.xxx格式,xx表示主表字段
/// 用户信息主要有用户账号:Account、昵称:UserName、真实姓名:RealName、头像:HeadIcon、手机号:MobilePhone
/// 输出对象请在Dtos中进行自行封装,不能是使用实体Model类
/// </summary>
/// <param name="condition">查询条件字段需要加表别名</param>
/// <param name="info">分页信息</param>
/// <param name="fieldToSort">排序字段,也需要加表别名</param>
/// <param name="desc">排序方式</param>
/// <param name="trans">事务</param>
/// <returns></returns>
List<object> FindWithPagerRelationUser(string condition, PagerInfo info, string fieldToSort, bool desc,
IDbTransaction trans = null);
/// <summary>
/// 根据条件统计数据
/// </summary>
/// <param name="condition">查询条件</param>
/// <param name="fieldName">统计字段名称</param>
/// <returns></returns>
int GetCountByWhere(string condition, string fieldName = "*");
/// <summary>
/// 根据条件统计数据
/// </summary>
/// <param name="condition">查询条件</param>
/// <param name="fieldName">统计字段名称</param>
/// <returns></returns>
Task<int> GetCountByWhereAsync(string condition, string fieldName = "*");
/// <summary>
/// 获取总条数
/// </summary>
/// <returns></returns>
Task<int> GetCount();
/// <summary>
/// 根据条件查询获取某个字段的最大值
/// </summary>
/// <param name="strField">字段</param>
/// <param name="where">条件</param>
/// <param name="trans">事务</param>
/// <returns>返回字段的最大值</returns>
Task<dynamic> GetMaxValueByFieldAsync(string strField, string where, IDbTransaction trans = null);
/// <summary>
/// 根据条件统计某个字段之和,sum(字段)
/// </summary>
/// <param name="strField">字段</param>
/// <param name="where">条件</param>
/// <param name="trans">事务</param>
/// <returns>返回字段求和后的值</returns>
Task<dynamic> GetSumValueByFieldAsync(string strField, string where, IDbTransaction trans = null);
/// <summary>
/// 多表操作--事务
/// </summary>
/// <param name="trans">事务</param>
/// <param name="commandTimeout">超时</param>
/// <returns></returns>
Task<Tuple<bool, string>>
ExecuteTransactionAsync(List<Tuple<string, object>> trans, int? commandTimeout = null);
/// <summary>
/// 多表操作--事务
/// </summary>
/// <param name="trans">事务</param>
/// <param name="commandTimeout">超时</param>
/// <returns></returns>
Tuple<bool, string> ExecuteTransaction(List<Tuple<string, object>> trans, int? commandTimeout = null);
}
}

55
Znyc.Cloudcar.Admin.Commons/Core/Models/BaseEntity.cs

@ -0,0 +1,55 @@
using System;
using System.ComponentModel;
namespace Znyc.Cloudcar.Admin.Commons.Entitys
{
/// <summary>
/// 定义领域对象框架实体类的基类,系统默认主键为Id
/// </summary>
/// <typeparam name="TKey">实体主键类型</typeparam>
[Serializable]
public abstract class BaseEntity<TKey> : Entity, IBaseEntity<TKey>
{
/// <summary>
/// 创建者Id
/// </summary>
[Description("创建者Id")]
public TKey CreatedUserId { get; set; }
/// <summary>
/// 创建时间
/// </summary>
[Description("创建时间")]
public DateTime CreatedTime { get; set; }
/// <summary>
/// 是否删除
/// </summary>
[Description("是否删除")]
public bool IsDeleted { get; set; } = false;
/// <summary>
/// 修改者Id
/// </summary>
[Description("修改者Id")]
public TKey ModifiedUserId { get; set; }
/// <summary>
/// 修改时间
/// </summary>
[Description("修改时间")]
public DateTime ModifiedTime { get; set; }
/// <summary>
/// Id
/// </summary>
[Description("Id")]
public TKey Id { get; set; }
}
/// <summary>
/// </summary>
public class BaseEntity : BaseEntity<long>
{
}
}

12
Znyc.Cloudcar.Admin.Commons/Core/Models/BaseViewModel.cs

@ -0,0 +1,12 @@
using System;
namespace Znyc.Cloudcar.Admin.Commons.Entitys
{
/// <summary>
/// 所有数据库视图对应实体类必须继承此类
/// </summary>
[Serializable]
public abstract class BaseViewModel : IEntity
{
}
}

9
Znyc.Cloudcar.Admin.Commons/Core/Models/Entity.cs

@ -0,0 +1,9 @@
namespace Znyc.Cloudcar.Admin.Commons.Entitys
{
/// <summary>
/// 实体基类
/// </summary>
public abstract class Entity : IEntity
{
}
}

14
Znyc.Cloudcar.Admin.Commons/Core/Models/IBaseEntity.cs

@ -0,0 +1,14 @@
namespace Znyc.Cloudcar.Admin.Commons.Entitys
{
/// <summary>
/// 数据模型接口
/// </summary>
/// <typeparam name="TKey">实体主键类型</typeparam>
public interface IBaseEntity<out TKey> : IEntity
{
/// <summary>
/// 获取 实体唯一标识,主键
/// </summary>
TKey Id { get; }
}
}

20
Znyc.Cloudcar.Admin.Commons/Core/Models/ICreationAudited.cs

@ -0,0 +1,20 @@
using System;
namespace Znyc.Cloudcar.Admin.Commons.Entitys
{
/// <summary>
/// 定义创建审计信息:给实体添加创建时的 创建人CreatedUserId,创建时间CreatedTime 的审计信息,这些值将在数据层执行 创建Insert 时自动赋值。
/// </summary>
public interface ICreationAudited
{
/// <summary>
/// 获取或设置 创建日期
/// </summary>
DateTime CreatedTime { get; set; }
/// <summary>
/// 获取或设置 创建用户主键
/// </summary>
long CreatedUserId { get; set; }
}
}

18
Znyc.Cloudcar.Admin.Commons/Core/Models/IDataAuthEnabled.cs

@ -0,0 +1,18 @@
namespace Znyc.Cloudcar.Admin.Commons.Entitys
{
/// <summary>
/// 定义数据权限的更新,删除状态
/// </summary>
public interface IDataAuthEnabled
{
/// <summary>
/// 获取或设置 是否可更新的数据权限状态
/// </summary>
bool Updatable { get; set; }
/// <summary>
/// 获取或设置 是否可删除的数据权限状态
/// </summary>
bool Deletable { get; set; }
}
}

13
Znyc.Cloudcar.Admin.Commons/Core/Models/IDeleteAudited.cs

@ -0,0 +1,13 @@
namespace Znyc.Cloudcar.Admin.Commons.Entitys
{
/// <summary>
/// 定义逻辑删除功能审计信息
/// </summary>
public interface IDeleteAudited
{
/// <summary>
/// 获取或设置 逻辑删除标记
/// </summary>
bool IsDeleted { get; set; }
}
}

9
Znyc.Cloudcar.Admin.Commons/Core/Models/IEntity.cs

@ -0,0 +1,9 @@
namespace Znyc.Cloudcar.Admin.Commons.Entitys
{
/// <summary>
/// 实体基接口,是所有实体的基接口
/// </summary>
public interface IEntity
{
}
}

10
Znyc.Cloudcar.Admin.Commons/Core/Models/IEntityHash.cs

@ -0,0 +1,10 @@
namespace Znyc.Cloudcar.Admin.Commons.Entitys
{
/// <summary>
/// 定义实体Hash功能,对实体的属性值进行Hash,确定实体是否存在变化,
/// 这些变化可用于系统初始化时确定是否需要进行数据同步
/// </summary>
public interface IEntityHash
{
}
}

20
Znyc.Cloudcar.Admin.Commons/Core/Models/IExpirable.cs

@ -0,0 +1,20 @@
using System;
namespace Znyc.Cloudcar.Admin.Commons.Entitys
{
/// <summary>
/// 定义可过期性,包含生效时间和过期时间:给实体添加 生效时间BeginTime,过期时间EndTime 的属性
/// </summary>
public interface IExpirable
{
/// <summary>
/// 获取或设置 生效时间
/// </summary>
DateTime? BeginTime { get; set; }
/// <summary>
/// 获取或设置 过期时间
/// </summary>
DateTime? EndTime { get; set; }
}
}

20
Znyc.Cloudcar.Admin.Commons/Core/Models/IModificationAudited.cs

@ -0,0 +1,20 @@
using System;
namespace Znyc.Cloudcar.Admin.Commons.Entitys
{
/// <summary>
/// 定义更新审计的信息
/// </summary>
public interface IModificationAudited
{
/// <summary>
/// 获取或设置 最后修改用户
/// </summary>
string ModifiedUserId { get; set; }
/// <summary>
/// 获取或设置 最后修改时间
/// </summary>
DateTime? ModifiedTime { get; set; }
}
}

13
Znyc.Cloudcar.Admin.Commons/Core/Models/IMustHaveTenant.cs

@ -0,0 +1,13 @@
namespace Znyc.Cloudcar.Admin.Commons.Entitys
{
/// <summary>
/// 定义多租户实体信息
/// </summary>
public interface IMustHaveTenant
{
/// <summary>
/// 租户Id
/// </summary>
string TenantId { get; set; }
}
}

22
Znyc.Cloudcar.Admin.Commons/Core/Module/AutoMapperService.cs

@ -0,0 +1,22 @@
using AutoMapper;
using Microsoft.Extensions.DependencyInjection;
using System;
using Znyc.Cloudcar.Admin.Commons.Mapping;
namespace Znyc.Cloudcar.Admin.Commons.Module
{
/// <summary>
/// AutoMapperService
/// </summary>
public class AutoMapperService
{
/// <summary>
/// </summary>
/// <param name="provider"></param>
public static void UsePack(IServiceProvider provider)
{
IMapper mapper = provider.GetService<IMapper>();
MapperExtensions.SetMapper(mapper);
}
}
}

88
Znyc.Cloudcar.Admin.Commons/Core/Module/MoudleService.cs

@ -0,0 +1,88 @@
using AutoMapper;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Yuebon.Commons.Repositories;
using Yuebon.Commons.IoC;
using Yuebon.Commons.Linq;
using Yuebon.Commons.Log;
namespace Yuebon.Commons.Module
{
/// <summary>
/// 模块服务
/// </summary>
public class MoudleService
{
/// <summary>
/// 实现应用模块程序集的注册服务
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
public static IServiceProvider LoaderMoudleService(IServiceCollection services)
{
// services.AddScoped(typeof(IUnitOfWork), typeof(UnitOfWork));
var apps = AppContext.BaseDirectory + "Apps";
if (!Directory.Exists(apps))
{
Directory.CreateDirectory(apps);
}
// 把 Apps 下的动态库拷贝一份来运行,
// 使 Apps 中的动态库不会在运行时被占用(以便重新编译)
var targetPath = PrepareShadowCopies();
// 从 Shadow Copy 目录加载 Assembly 并注册到 Mvc 中
//LoadFromShadowCopies(targetPath);
string PrepareShadowCopies()
{
// 准备 Shadow Copy 的目标目录
var target = Path.Combine(AppContext.BaseDirectory, "app_data", "apps-cache");
if (!Directory.Exists(target))
{
Directory.CreateDirectory(target);
}
// 找到插件目录下 bin 目录中的 .dll,拷贝
Directory.EnumerateDirectories(apps)
.Select(path => Path.Combine(path, "bin"))
.Where(Directory.Exists)
.SelectMany(bin => Directory.EnumerateFiles(bin, "*.dll"))
.ForEach(dll => File.Copy(dll, Path.Combine(target, Path.GetFileName(dll)), true));
return target;
}
DirectoryInfo folder = new DirectoryInfo(targetPath);
List<Assembly> myAssembly = new List<Assembly>();
myAssembly.Add(Assembly.Load("Yuebon.Security.Core"));
if (File.Exists(AppContext.BaseDirectory+ "Yuebon.Messages.Core.dll"))
{
myAssembly.Add(Assembly.Load("Yuebon.Messages.Core"));
}
foreach (FileInfo finfo in folder.GetFiles("*.Core.dll"))
{
try
{
myAssembly.Add(Assembly.LoadFrom(finfo.FullName));
string dllNamespaceStr = finfo.Name.Substring(0, finfo.Name.IndexOf(".Core"));
IoCContainer.RegisterFrom(finfo.FullName);
IoCContainer.RegisterLoadFrom(finfo.FullName, dllNamespaceStr);
Log4NetHelper.Info("注入应用模块" + finfo.Name + "成功");
}
catch (Exception ex)
{
Log4NetHelper.Error("注入应用模块" + finfo.Name + "失败\r\n" , ex);
}
}
services.AddAutoMapper(myAssembly);
services.AddScoped<IMapper, Mapper>();
return IoCContainer.Build(services);
}
}
}

2255
Znyc.Cloudcar.Admin.Commons/Core/Repositories/BaseRepository.cs

File diff suppressed because it is too large

1006
Znyc.Cloudcar.Admin.Commons/Core/Services/BaseService.cs

File diff suppressed because it is too large

22
Znyc.Cloudcar.Admin.Commons/Cos/CosOptions.cs

@ -0,0 +1,22 @@
namespace Znyc.Cloudcar.Admin.Commons.Cos
{
/// <summary>
/// Cos储存桶配置
/// </summary>
public class CosOptions
{
public string SecretId { get; set; }
public string SecretKey { get; set; }
public string Bucket { get; set; }
public string Region { get; set; }
public string AllowPrefix { get; set; }
public int DurationSeconds { get; set; }
public string[] AllowActions { get; set; }
}
}

251
Znyc.Cloudcar.Admin.Commons/Data/Check.cs

@ -0,0 +1,251 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Znyc.Cloudcar.Admin.Commons.Dtos;
using Znyc.Cloudcar.Admin.Commons.Properties;
namespace Znyc.Cloudcar.Admin.Commons.Data
{
/// <summary>
/// 参数合法性检查类
/// </summary>
[DebuggerStepThrough]
public static class Check
{
/// <summary>
/// 验证指定值的断言<paramref name="assertion" />是否为真,如果不为真,抛出指定消息<paramref name="message" />的指定类型
/// <typeparamref name="TException" />异常
/// </summary>
/// <typeparam name="TException">异常类型</typeparam>
/// <param name="assertion">要验证的断言。</param>
/// <param name="message">异常消息。</param>
private static void Require<TException>(bool assertion, string message)
where TException : Exception
{
if (assertion)
{
return;
}
if (string.IsNullOrEmpty(message))
{
throw new ArgumentNullException(nameof(message));
}
TException exception = (TException)Activator.CreateInstance(typeof(TException), message);
throw exception;
}
/// <summary>
/// 验证指定值的断言表达式是否为真,不为值抛出<see cref="Exception" />异常
/// </summary>
/// <param name="value"></param>
/// <param name="assertionFunc">要验证的断言表达式</param>
/// <param name="message">异常消息</param>
public static void Required<T>(T value, Func<T, bool> assertionFunc, string message)
{
if (assertionFunc == null)
{
throw new ArgumentNullException(nameof(assertionFunc));
}
Require<Exception>(assertionFunc(value), message);
}
/// <summary>
/// 验证指定值的断言表达式是否为真,不为真抛出<typeparamref name="TException" />异常
/// </summary>
/// <typeparam name="T">要判断的值的类型</typeparam>
/// <typeparam name="TException">抛出的异常类型</typeparam>
/// <param name="value">要判断的值</param>
/// <param name="assertionFunc">要验证的断言表达式</param>
/// <param name="message">异常消息</param>
public static void Required<T, TException>(T value, Func<T, bool> assertionFunc, string message)
where TException : Exception
{
if (assertionFunc == null)
{
throw new ArgumentNullException("assertionFunc");
}
Require<TException>(assertionFunc(value), message);
}
/// <summary>
/// 检查参数不能为空引用,否则抛出<see cref="ArgumentNullException" />异常。
/// </summary>
/// <param name="value"></param>
/// <param name="paramName">参数名称</param>
/// <exception cref="ArgumentNullException"></exception>
public static void NotNull<T>(T value, string paramName)
{
Require<ArgumentNullException>(value != null, string.Format(Resources.ParameterCheck_NotNull, paramName));
}
/// <summary>
/// 检查字符串不能为空引用或空字符串,否则抛出<see cref="ArgumentNullException" />异常或<see cref="ArgumentException" />异常。
/// </summary>
/// <param name="value"></param>
/// <param name="paramName">参数名称。</param>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="ArgumentException"></exception>
public static void NotNullOrEmpty(string value, string paramName)
{
Require<ArgumentException>(!string.IsNullOrEmpty(value),
string.Format(Resources.ParameterCheck_NotNullOrEmpty_String, paramName));
}
/// <summary>
/// 检查Guid值不能为Guid.Empty,否则抛出<see cref="ArgumentException" />异常。
/// </summary>
/// <param name="value"></param>
/// <param name="paramName">参数名称。</param>
/// <exception cref="ArgumentException"></exception>
public static void NotEmpty(Guid value, string paramName)
{
Require<ArgumentException>(value != Guid.Empty,
string.Format(Resources.ParameterCheck_NotEmpty_Guid, paramName));
}
/// <summary>
/// 检查集合不能为空引用或空集合,否则抛出<see cref="ArgumentNullException" />异常或<see cref="ArgumentException" />异常。
/// </summary>
/// <typeparam name="T">集合项的类型。</typeparam>
/// <param name="list"></param>
/// <param name="paramName">参数名称。</param>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="ArgumentException"></exception>
public static void NotNullOrEmpty<T>(IReadOnlyList<T> list, string paramName)
{
NotNull(list, paramName);
Require<ArgumentException>(list.Any(),
string.Format(Resources.ParameterCheck_NotNullOrEmpty_Collection, paramName));
}
/// <summary>
/// 检查集合中没有包含值为null的项
/// </summary>
public static void HasNoNulls<T>(IReadOnlyList<T> list, string paramName)
{
NotNull(list, paramName);
Require<ArgumentException>(list.All(m => m != null),
string.Format(Resources.ParameterCheck_NotContainsNull_Collection, paramName));
}
/// <summary>
/// 检查参数必须小于[或可等于,参数<paramref name="canEqual" />]指定值,否则抛出<see cref="ArgumentOutOfRangeException" />异常。
/// </summary>
/// <typeparam name="T">参数类型。</typeparam>
/// <param name="value"></param>
/// <param name="paramName">参数名称。</param>
/// <param name="target">要比较的值。</param>
/// <param name="canEqual">是否可等于。</param>
/// <exception cref="ArgumentOutOfRangeException"></exception>
public static void LessThan<T>(T value, string paramName, T target, bool canEqual = false)
where T : IComparable<T>
{
bool flag = canEqual ? value.CompareTo(target) <= 0 : value.CompareTo(target) < 0;
string format = canEqual ? Resources.ParameterCheck_NotLessThanOrEqual : Resources.ParameterCheck_NotLessThan;
Require<ArgumentOutOfRangeException>(flag, string.Format(format, paramName, target));
}
/// <summary>
/// 检查参数必须大于[或可等于,参数<paramref name="canEqual" />]指定值,否则抛出<see cref="ArgumentOutOfRangeException" />异常。
/// </summary>
/// <typeparam name="T">参数类型。</typeparam>
/// <param name="value"></param>
/// <param name="paramName">参数名称。</param>
/// <param name="target">要比较的值。</param>
/// <param name="canEqual">是否可等于。</param>
/// <exception cref="ArgumentOutOfRangeException"></exception>
public static void GreaterThan<T>(T value, string paramName, T target, bool canEqual = false)
where T : IComparable<T>
{
bool flag = canEqual ? value.CompareTo(target) >= 0 : value.CompareTo(target) > 0;
string format = canEqual
? Resources.ParameterCheck_NotGreaterThanOrEqual
: Resources.ParameterCheck_NotGreaterThan;
Require<ArgumentOutOfRangeException>(flag, string.Format(format, paramName, target));
}
/// <summary>
/// 检查参数必须在指定范围之间,否则抛出<see cref="ArgumentOutOfRangeException" />异常。
/// </summary>
/// <typeparam name="T">参数类型。</typeparam>
/// <param name="value"></param>
/// <param name="paramName">参数名称。</param>
/// <param name="start">比较范围的起始值。</param>
/// <param name="end">比较范围的结束值。</param>
/// <param name="startEqual">是否可等于起始值</param>
/// <param name="endEqual">是否可等于结束值</param>
/// <exception cref="ArgumentOutOfRangeException"></exception>
public static void Between<T>(T value, string paramName, T start, T end, bool startEqual = false,
bool endEqual = false)
where T : IComparable<T>
{
bool flag = startEqual ? value.CompareTo(start) >= 0 : value.CompareTo(start) > 0;
string message = startEqual
? string.Format(Resources.ParameterCheck_Between, paramName, start, end)
: string.Format(Resources.ParameterCheck_BetweenNotEqual, paramName, start, end, start);
Require<ArgumentOutOfRangeException>(flag, message);
flag = endEqual ? value.CompareTo(end) <= 0 : value.CompareTo(end) < 0;
message = endEqual
? string.Format(Resources.ParameterCheck_Between, paramName, start, end)
: string.Format(Resources.ParameterCheck_BetweenNotEqual, paramName, start, end, end);
Require<ArgumentOutOfRangeException>(flag, message);
}
/// <summary>
/// 检查指定路径的文件夹必须存在,否则抛出<see cref="DirectoryNotFoundException" />异常。
/// </summary>
/// <param name="directory"></param>
/// <param name="paramName">参数名称。</param>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="DirectoryNotFoundException"></exception>
public static void DirectoryExists(string directory, string paramName = null)
{
NotNull(directory, paramName);
Require<DirectoryNotFoundException>(Directory.Exists(directory),
string.Format(Resources.ParameterCheck_DirectoryNotExists, directory));
}
/// <summary>
/// 检查指定路径的文件必须存在,否则抛出<see cref="FileNotFoundException" />异常。
/// </summary>
/// <param name="filename"></param>
/// <param name="paramName">参数名称。</param>
/// <exception cref="ArgumentNullException">当文件路径为null时</exception>
/// <exception cref="FileNotFoundException">当文件路径不存在时</exception>
public static void FileExists(string filename, string paramName = null)
{
NotNull(filename, paramName);
Require<FileNotFoundException>(File.Exists(filename),
string.Format(Resources.ParameterCheck_FileNotExists, filename));
}
/// <summary>
/// 检查<see cref="IInputDto{TKey}" />各属性的合法性,否则抛出<see cref="ValidationException" />异常
/// </summary>
public static void Validate<TKey>(IInputDto<TKey> dto, string paramName)
{
NotNull(dto, paramName);
dto.Validate();
}
/// <summary>
/// 检查<see cref="IInputDto{TKey}" />各属性的合法性,否则抛出<see cref="ValidationException" />异常
/// </summary>
public static void Validate<TInputDto, TKey>(TInputDto[] dtos, string paramName)
where TInputDto : IInputDto<TKey>
{
NotNull(dtos, paramName);
foreach (TInputDto dto in dtos)
{
dto.Validate();
}
}
}
}

95
Znyc.Cloudcar.Admin.Commons/Data/MicroDataTable.cs

@ -0,0 +1,95 @@
using System;
using System.Collections.Generic;
namespace Znyc.Cloudcar.Admin.Commons.Data
{
/// <summary>
/// 查询结果数据表样式
/// </summary>
public class MicroDataTable
{
/// <summary>
/// 整个查询语句结果的总条数,而非本DataTable的条数
/// </summary>
public int TotalCount { get; set; }
/// <summary>
/// 数据列名称
/// </summary>
public List<MicroDataColumn> Columns { get; set; } = new();
/// <summary>
/// 数据记录
/// </summary>
public List<MicroDataRow> Rows { get; set; } = new();
/// <summary>
/// 主键
/// </summary>
public MicroDataColumn[] PrimaryKey { get; set; }
public MicroDataRow NewRow()
{
return new(Columns, new object[Columns.Count]);
}
}
public class MicroDataColumn
{
public string ColumnName { get; set; }
public Type ColumnType { get; set; }
}
public class MicroDataRow
{
private readonly object[] _ItemArray;
public MicroDataRow(List<MicroDataColumn> columns, object[] itemArray)
{
Columns = columns;
_ItemArray = itemArray;
}
public List<MicroDataColumn> Columns { get; }
public object this[int index]
{
get => _ItemArray[index];
set => _ItemArray[index] = value;
}
public object this[string columnName]
{
get
{
int i = 0;
foreach (MicroDataColumn column in Columns)
{
if (column.ColumnName == columnName)
{
break;
}
i++;
}
return _ItemArray[i];
}
set
{
int i = 0;
foreach (MicroDataColumn column in Columns)
{
if (column.ColumnName == columnName)
{
break;
}
i++;
}
_ItemArray[i] = value;
}
}
}
}

52
Znyc.Cloudcar.Admin.Commons/Data/MicroDataTableHelper.cs

@ -0,0 +1,52 @@
using System.Data.Common;
namespace Znyc.Cloudcar.Admin.Commons.Data
{
public class MicroDataTableHelper
{
/// <summary>
/// DbDataReaders 数据转化Datatable
/// </summary>
/// <param name="reader"></param>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <returns></returns>
public static MicroDataTable FillDataTable(DbDataReader reader, int pageIndex, int pageSize)
{
bool defined = false;
MicroDataTable table = new MicroDataTable();
int index = 0;
int beginIndex = pageSize * pageIndex;
int endIndex = pageSize * (pageIndex + 1) - 1;
while (reader.Read())
{
object[] values = new object[reader.FieldCount];
if (!defined)
{
for (int i = 0; i < reader.FieldCount; i++)
{
MicroDataColumn column = new MicroDataColumn
{
ColumnName = reader.GetName(i),
ColumnType = reader.GetFieldType(i)
};
table.Columns.Add(column);
}
defined = true;
}
if (index >= beginIndex && index <= endIndex)
{
reader.GetValues(values);
table.Rows.Add(new MicroDataRow(table.Columns, values));
}
index++;
}
table.TotalCount = index;
return table;
}
}
}

9
Znyc.Cloudcar.Admin.Commons/DependencyInjection/IPrivateDependency.cs

@ -0,0 +1,9 @@
namespace Znyc.Cloudcar.Admin.Commons.DependencyInjection
{
/// <summary>
/// 依赖空接口(禁止外部继承)
/// </summary>
public interface IPrivateDependency
{
}
}

9
Znyc.Cloudcar.Admin.Commons/DependencyInjection/IScopedDependency.cs

@ -0,0 +1,9 @@
namespace Znyc.Cloudcar.Admin.Commons.DependencyInjection
{
/// <summary>
/// 作用域服务注册依赖
/// </summary>
public interface IScopedDependency : IPrivateDependency
{
}
}

9
Znyc.Cloudcar.Admin.Commons/DependencyInjection/ISingletonDependency.cs

@ -0,0 +1,9 @@
namespace Znyc.Cloudcar.Admin.Commons.DependencyInjection
{
/// <summary>
/// 单例服务注册依赖
/// </summary>
public interface ISingletonDependency : IPrivateDependency
{
}
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save