├── .gitattributes ├── .gitignore ├── DMicroservices.sln ├── DMicroservices ├── Base │ ├── Attributes │ │ └── DisableChangeTrackAtrribute.cs │ ├── Controllers │ │ ├── CrudController.cs │ │ └── IdentityCrudController.cs │ └── Identity │ │ └── IdentityFilter.cs ├── DMicroservices.csproj ├── DataAccess │ ├── Cache │ │ └── MemoryCacheManager.cs │ ├── DynamicQuery │ │ ├── Enum │ │ │ ├── SortTypeEnum.cs │ │ │ └── TypePropertyEnum.cs │ │ ├── FilterCompareTypesItem.cs │ │ ├── FilterItemDto.cs │ │ ├── OrderItemDto.cs │ │ ├── SelectDto.cs │ │ └── SortItemDto.cs │ ├── ElasticSearch │ │ ├── ElasticHelper.cs │ │ └── IElasticRepository.cs │ ├── HealthCheck │ │ ├── DatabaseHealthCheck.cs │ │ └── RedisHealthCheck.cs │ ├── History │ │ └── HistoryCollectionModel.cs │ ├── MongoRepository │ │ ├── Base │ │ │ └── MongoBaseModel.cs │ │ ├── Interfaces │ │ │ ├── IDatabaseSettings.cs │ │ │ └── IMongoRepository.cs │ │ ├── MongoRepository.cs │ │ ├── MongoRepositoryFactory.cs │ │ └── Settings │ │ │ └── DatabaseSettings.cs │ ├── Redis │ │ ├── RedisList.cs │ │ └── RedisManager.cs │ ├── Repository │ │ ├── FilteredReadonlyRepository.cs │ │ ├── FilteredRepository.cs │ │ ├── IRepository.cs │ │ ├── ReadonlyRepository.cs │ │ └── Repository.cs │ └── UnitOfWork │ │ ├── ICustomDbContext.cs │ │ ├── IUnitOfWork.cs │ │ ├── UnitOfWork.cs │ │ ├── UnitOfWorkFactory.cs │ │ ├── UnitOfWorkFactoryBase.cs │ │ └── UnitOfWorkSettings.cs ├── LICENSE ├── Properties │ └── launchSettings.json ├── RabbitMq │ ├── Base │ │ ├── ConsumerRegistry.cs │ │ ├── ListenQueueAttribute.cs │ │ ├── RabbitMQConnection.cs │ │ └── RabbitMqHealthCheck.cs │ ├── ConstantString.cs │ ├── Consumer │ │ ├── BasicConsumer.cs │ │ ├── BasicRawConsumer.cs │ │ └── IBasicConsumer.cs │ ├── Model │ │ ├── ConnectionType.cs │ │ ├── ConsumerActiveModel.cs │ │ └── ExchangeContent.cs │ └── Producer │ │ └── BasicPublisher.cs └── Utils │ ├── Exceptions │ └── RabbitMqConnectionException.cs │ ├── Extensions │ ├── ConnectionExtensions.cs │ ├── CryptoExtensions.cs │ ├── DatabaseExtensions.cs │ ├── ExpressionExtensions.cs │ └── OverloadedMethodFinder.cs │ ├── Logger │ └── ElasticLogger.cs │ ├── ObjectMapper │ └── ObjectMapper.cs │ └── RestSharp │ └── CustomRestClient.cs ├── README.md └── Tests ├── DMicroservices.DataAccess.Tests ├── DMicroservices.DataAccess.Tests.csproj ├── MasterContext.cs ├── Migrations │ ├── 20210125133956_v1.Designer.cs │ ├── 20210125133956_v1.cs │ ├── 20210125143139_v2.Designer.cs │ ├── 20210125143139_v2.cs │ ├── 20210208080618_v3.Designer.cs │ ├── 20210208080618_v3.cs │ ├── 20220427093400_v5.Designer.cs │ ├── 20220427093400_v5.cs │ ├── 20221017124037_v6.Designer.cs │ ├── 20221017124037_v6.cs │ ├── 20230322133308_tet.Designer.cs │ ├── 20230322133308_tet.cs │ └── MasterContextModelSnapshot.cs ├── Models │ ├── City.cs │ ├── Document.cs │ ├── Person.cs │ ├── Search.cs │ ├── Student.cs │ └── Teacher.cs ├── Program.cs └── Properties │ └── launchSettings.json └── DMicroservices.RabbitMq.Test ├── DMicroservices.RabbitMq.Test.csproj ├── ExampleConsumer.cs ├── ExampleConsumer2.cs ├── ExampleModel.cs ├── ExchangeConsumer.cs ├── Program.cs ├── Properties └── launchSettings.json └── TestConsumer.cs /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Build results 17 | [Dd]ebug/ 18 | [Dd]ebugPublic/ 19 | [Rr]elease/ 20 | [Rr]eleases/ 21 | x64/ 22 | x86/ 23 | [Aa][Rr][Mm]/ 24 | [Aa][Rr][Mm]64/ 25 | bld/ 26 | [Bb]in/ 27 | [Oo]bj/ 28 | [Ll]og/ 29 | 30 | # Visual Studio 2015/2017 cache/options directory 31 | .vs/ 32 | # Uncomment if you have tasks that create the project's static files in wwwroot 33 | #wwwroot/ 34 | 35 | # Visual Studio 2017 auto generated files 36 | Generated\ Files/ 37 | 38 | # MSTest test Results 39 | [Tt]est[Rr]esult*/ 40 | [Bb]uild[Ll]og.* 41 | 42 | # NUNIT 43 | *.VisualState.xml 44 | TestResult.xml 45 | 46 | # Build Results of an ATL Project 47 | [Dd]ebugPS/ 48 | [Rr]eleasePS/ 49 | dlldata.c 50 | 51 | # Benchmark Results 52 | BenchmarkDotNet.Artifacts/ 53 | 54 | # .NET Core 55 | project.lock.json 56 | project.fragment.lock.json 57 | artifacts/ 58 | 59 | # StyleCop 60 | StyleCopReport.xml 61 | 62 | # Files built by Visual Studio 63 | *_i.c 64 | *_p.c 65 | *_h.h 66 | *.ilk 67 | *.meta 68 | *.obj 69 | *.iobj 70 | *.pch 71 | *.pdb 72 | *.ipdb 73 | *.pgc 74 | *.pgd 75 | *.rsp 76 | *.sbr 77 | *.tlb 78 | *.tli 79 | *.tlh 80 | *.tmp 81 | *.tmp_proj 82 | *_wpftmp.csproj 83 | *.log 84 | *.vspscc 85 | *.vssscc 86 | .builds 87 | *.pidb 88 | *.svclog 89 | *.scc 90 | 91 | # Chutzpah Test files 92 | _Chutzpah* 93 | 94 | # Visual C++ cache files 95 | ipch/ 96 | *.aps 97 | *.ncb 98 | *.opendb 99 | *.opensdf 100 | *.sdf 101 | *.cachefile 102 | *.VC.db 103 | *.VC.VC.opendb 104 | 105 | # Visual Studio profiler 106 | *.psess 107 | *.vsp 108 | *.vspx 109 | *.sap 110 | 111 | # Visual Studio Trace Files 112 | *.e2e 113 | 114 | # TFS 2012 Local Workspace 115 | $tf/ 116 | 117 | # Guidance Automation Toolkit 118 | *.gpState 119 | 120 | # ReSharper is a .NET coding add-in 121 | _ReSharper*/ 122 | *.[Rr]e[Ss]harper 123 | *.DotSettings.user 124 | 125 | # JustCode is a .NET coding add-in 126 | .JustCode 127 | 128 | # TeamCity is a build add-in 129 | _TeamCity* 130 | 131 | # DotCover is a Code Coverage Tool 132 | *.dotCover 133 | 134 | # AxoCover is a Code Coverage Tool 135 | .axoCover/* 136 | !.axoCover/settings.json 137 | 138 | # Visual Studio code coverage results 139 | *.coverage 140 | *.coveragexml 141 | 142 | # NCrunch 143 | _NCrunch_* 144 | .*crunch*.local.xml 145 | nCrunchTemp_* 146 | 147 | # MightyMoose 148 | *.mm.* 149 | AutoTest.Net/ 150 | 151 | # Web workbench (sass) 152 | .sass-cache/ 153 | 154 | # Installshield output folder 155 | [Ee]xpress/ 156 | 157 | # DocProject is a documentation generator add-in 158 | DocProject/buildhelp/ 159 | DocProject/Help/*.HxT 160 | DocProject/Help/*.HxC 161 | DocProject/Help/*.hhc 162 | DocProject/Help/*.hhk 163 | DocProject/Help/*.hhp 164 | DocProject/Help/Html2 165 | DocProject/Help/html 166 | 167 | # Click-Once directory 168 | publish/ 169 | 170 | # Publish Web Output 171 | *.[Pp]ublish.xml 172 | *.azurePubxml 173 | # Note: Comment the next line if you want to checkin your web deploy settings, 174 | # but database connection strings (with potential passwords) will be unencrypted 175 | *.pubxml 176 | *.publishproj 177 | 178 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 179 | # checkin your Azure Web App publish settings, but sensitive information contained 180 | # in these scripts will be unencrypted 181 | PublishScripts/ 182 | 183 | # NuGet Packages 184 | *.nupkg 185 | # The packages folder can be ignored because of Package Restore 186 | **/[Pp]ackages/* 187 | # except build/, which is used as an MSBuild target. 188 | !**/[Pp]ackages/build/ 189 | # Uncomment if necessary however generally it will be regenerated when needed 190 | #!**/[Pp]ackages/repositories.config 191 | # NuGet v3's project.json files produces more ignorable files 192 | *.nuget.props 193 | *.nuget.targets 194 | 195 | # Microsoft Azure Build Output 196 | csx/ 197 | *.build.csdef 198 | 199 | # Microsoft Azure Emulator 200 | ecf/ 201 | rcf/ 202 | 203 | # Windows Store app package directories and files 204 | AppPackages/ 205 | BundleArtifacts/ 206 | Package.StoreAssociation.xml 207 | _pkginfo.txt 208 | *.appx 209 | 210 | # Visual Studio cache files 211 | # files ending in .cache can be ignored 212 | *.[Cc]ache 213 | # but keep track of directories ending in .cache 214 | !?*.[Cc]ache/ 215 | 216 | # Others 217 | ClientBin/ 218 | ~$* 219 | *~ 220 | *.dbmdl 221 | *.dbproj.schemaview 222 | *.jfm 223 | *.pfx 224 | *.publishsettings 225 | orleans.codegen.cs 226 | 227 | # Including strong name files can present a security risk 228 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 229 | #*.snk 230 | 231 | # Since there are multiple workflows, uncomment next line to ignore bower_components 232 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 233 | #bower_components/ 234 | 235 | # RIA/Silverlight projects 236 | Generated_Code/ 237 | 238 | # Backup & report files from converting an old project file 239 | # to a newer Visual Studio version. Backup files are not needed, 240 | # because we have git ;-) 241 | _UpgradeReport_Files/ 242 | Backup*/ 243 | UpgradeLog*.XML 244 | UpgradeLog*.htm 245 | ServiceFabricBackup/ 246 | *.rptproj.bak 247 | 248 | # SQL Server files 249 | *.mdf 250 | *.ldf 251 | *.ndf 252 | 253 | # Business Intelligence projects 254 | *.rdl.data 255 | *.bim.layout 256 | *.bim_*.settings 257 | *.rptproj.rsuser 258 | *- Backup*.rdl 259 | 260 | # Microsoft Fakes 261 | FakesAssemblies/ 262 | 263 | # GhostDoc plugin setting file 264 | *.GhostDoc.xml 265 | 266 | # Node.js Tools for Visual Studio 267 | .ntvs_analysis.dat 268 | node_modules/ 269 | 270 | # Visual Studio 6 build log 271 | *.plg 272 | 273 | # Visual Studio 6 workspace options file 274 | *.opt 275 | 276 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 277 | *.vbw 278 | 279 | # Visual Studio LightSwitch build output 280 | **/*.HTMLClient/GeneratedArtifacts 281 | **/*.DesktopClient/GeneratedArtifacts 282 | **/*.DesktopClient/ModelManifest.xml 283 | **/*.Server/GeneratedArtifacts 284 | **/*.Server/ModelManifest.xml 285 | _Pvt_Extensions 286 | 287 | # Paket dependency manager 288 | .paket/paket.exe 289 | paket-files/ 290 | 291 | # FAKE - F# Make 292 | .fake/ 293 | 294 | # JetBrains Rider 295 | .idea/ 296 | *.sln.iml 297 | 298 | # CodeRush personal settings 299 | .cr/personal 300 | 301 | # Python Tools for Visual Studio (PTVS) 302 | __pycache__/ 303 | *.pyc 304 | 305 | # Cake - Uncomment if you are using it 306 | # tools/** 307 | # !tools/packages.config 308 | 309 | # Tabs Studio 310 | *.tss 311 | 312 | # Telerik's JustMock configuration file 313 | *.jmconfig 314 | 315 | # BizTalk build output 316 | *.btp.cs 317 | *.btm.cs 318 | *.odx.cs 319 | *.xsd.cs 320 | 321 | # OpenCover UI analysis results 322 | OpenCover/ 323 | 324 | # Azure Stream Analytics local run output 325 | ASALocalRun/ 326 | 327 | # MSBuild Binary and Structured Log 328 | *.binlog 329 | 330 | # NVidia Nsight GPU debugger configuration file 331 | *.nvuser 332 | 333 | # MFractors (Xamarin productivity tool) working folder 334 | .mfractor/ 335 | 336 | # Local History for Visual Studio 337 | .localhistory/ 338 | 339 | # BeatPulse healthcheck temp database 340 | healthchecksdb -------------------------------------------------------------------------------- /DMicroservices.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30717.126 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Test", "Test", "{95570331-64A2-49BC-A7DB-16A83BFD6D03}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DMicroservices.DataAccess.Tests", "Tests\DMicroservices.DataAccess.Tests\DMicroservices.DataAccess.Tests.csproj", "{5F64AAD9-19EE-45EA-89C1-0B0FFEDADEAD}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DMicroservices.RabbitMq.Test", "Tests\DMicroservices.RabbitMq.Test\DMicroservices.RabbitMq.Test.csproj", "{ACE87BA3-02F5-49E8-8E40-BD3651CFD67A}" 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DMicroservices", "DMicroservices\DMicroservices.csproj", "{5D4845ED-73E0-44B1-951A-CB7F237161F1}" 13 | EndProject 14 | Global 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 16 | Debug|Any CPU = Debug|Any CPU 17 | Release|Any CPU = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {5F64AAD9-19EE-45EA-89C1-0B0FFEDADEAD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {5F64AAD9-19EE-45EA-89C1-0B0FFEDADEAD}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {5F64AAD9-19EE-45EA-89C1-0B0FFEDADEAD}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {5F64AAD9-19EE-45EA-89C1-0B0FFEDADEAD}.Release|Any CPU.Build.0 = Release|Any CPU 24 | {ACE87BA3-02F5-49E8-8E40-BD3651CFD67A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {ACE87BA3-02F5-49E8-8E40-BD3651CFD67A}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {ACE87BA3-02F5-49E8-8E40-BD3651CFD67A}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {ACE87BA3-02F5-49E8-8E40-BD3651CFD67A}.Release|Any CPU.Build.0 = Release|Any CPU 28 | {5D4845ED-73E0-44B1-951A-CB7F237161F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {5D4845ED-73E0-44B1-951A-CB7F237161F1}.Debug|Any CPU.Build.0 = Debug|Any CPU 30 | {5D4845ED-73E0-44B1-951A-CB7F237161F1}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {5D4845ED-73E0-44B1-951A-CB7F237161F1}.Release|Any CPU.Build.0 = Release|Any CPU 32 | EndGlobalSection 33 | GlobalSection(SolutionProperties) = preSolution 34 | HideSolutionNode = FALSE 35 | EndGlobalSection 36 | GlobalSection(NestedProjects) = preSolution 37 | {5F64AAD9-19EE-45EA-89C1-0B0FFEDADEAD} = {95570331-64A2-49BC-A7DB-16A83BFD6D03} 38 | {ACE87BA3-02F5-49E8-8E40-BD3651CFD67A} = {95570331-64A2-49BC-A7DB-16A83BFD6D03} 39 | EndGlobalSection 40 | GlobalSection(ExtensibilityGlobals) = postSolution 41 | SolutionGuid = {23652937-9489-427B-91AA-2141C0099556} 42 | EndGlobalSection 43 | EndGlobal 44 | -------------------------------------------------------------------------------- /DMicroservices/Base/Attributes/DisableChangeTrackAtrribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace DMicroservices.Base.Attributes 4 | { 5 | [AttributeUsage(AttributeTargets.Property)] 6 | public class DisableChangeTrackAttribute : Attribute 7 | { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /DMicroservices/Base/Controllers/CrudController.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using DMicroservices.DataAccess.DynamicQuery; 3 | using DMicroservices.DataAccess.UnitOfWork; 4 | using DMicroservices.Utils.Extensions; 5 | using DMicroservices.Utils.ObjectMapper; 6 | using Microsoft.AspNetCore.Mvc; 7 | using Microsoft.EntityFrameworkCore; 8 | 9 | namespace DMicroservices.Base.Controllers 10 | { 11 | /// 12 | /// CrudController is a generic crud operations based WebApi controller. 13 | /// This controller contains only base CRUD operations. 14 | /// 15 | public class CrudController : Controller 16 | where D : DbContext, ICustomDbContext 17 | where T : class 18 | { 19 | 20 | [HttpGet] 21 | [Route("{id}")] 22 | public IActionResult Get(long id) 23 | { 24 | using (var uow = new UnitOfWork()) 25 | { 26 | var repository = uow.GetRepository(); 27 | T item = repository.GetAll(id.GetIdentifierExpression()) 28 | .Include(repository.GetDbContext().GetIncludePaths(typeof(T))).FirstOrDefault(); 29 | 30 | if (item == null) 31 | return StatusCode(404); 32 | return Json(item); 33 | } 34 | } 35 | 36 | [HttpPost] 37 | [Route("DynamicQuery")] 38 | public IActionResult DynamicQuery([FromBody] SelectDto selectDto) 39 | { 40 | using (var uow = new UnitOfWork()) 41 | { 42 | var repository = uow.GetRepository(); 43 | return Json(repository.GetAll(selectDto.GetExpression()) 44 | .Include(repository.GetDbContext().GetIncludePaths(typeof(T))).ToList()); 45 | } 46 | } 47 | 48 | 49 | [HttpPut] 50 | public IActionResult Put([FromBody]T item) 51 | { 52 | using (var uow = new UnitOfWork()) 53 | { 54 | uow.GetRepository().Add(item); 55 | if (uow.SaveChanges() > 0) 56 | return Json(item); 57 | return StatusCode(500); 58 | } 59 | } 60 | 61 | [HttpDelete] 62 | [Route("{id}")] 63 | public IActionResult Delete(long id) 64 | { 65 | using (var uow = new UnitOfWork()) 66 | { 67 | T item = uow.GetRepository().Get(id.GetIdentifierExpression()); 68 | if (item == null) 69 | return StatusCode(404); 70 | 71 | uow.GetRepository().Delete(item); 72 | return StatusCode(uow.SaveChanges() > 0 ? 200 : 500); 73 | } 74 | } 75 | 76 | [HttpPost] 77 | [Route("{id}")] 78 | public IActionResult Update(long id, [FromBody] T updateItem) 79 | { 80 | using (var uow = new UnitOfWork()) 81 | { 82 | T item = uow.GetRepository().Get(id.GetIdentifierExpression()); 83 | if (item == null) 84 | return StatusCode(404); 85 | 86 | ObjectMapper.MapExclude(item, updateItem, new string[] { typeof(T).GetIdentifierColumnName() }); 87 | uow.GetRepository().Update(item); 88 | return StatusCode(uow.SaveChanges() > 0 ? 200 : 500); 89 | } 90 | } 91 | 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /DMicroservices/Base/Controllers/IdentityCrudController.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using DMicroservices.Base.Identity; 3 | using DMicroservices.DataAccess.DynamicQuery; 4 | using DMicroservices.DataAccess.UnitOfWork; 5 | using DMicroservices.Utils.Extensions; 6 | using DMicroservices.Utils.ObjectMapper; 7 | using Microsoft.AspNetCore.Mvc; 8 | using Microsoft.EntityFrameworkCore; 9 | 10 | namespace DMicroservices.Base.Controllers 11 | { 12 | /// 13 | /// CrudController is a generic crud operations based WebApi controller. 14 | /// This controller contains only base CRUD operations. 15 | /// 16 | public class IdentityCrudController : Controller 17 | where TD : DbContext, ICustomDbContext 18 | where T : class 19 | { 20 | 21 | [HttpGet] 22 | [Route("{id}")] 23 | public IActionResult Get(long id) 24 | { 25 | using (var uow = new UnitOfWork()) 26 | { 27 | var repository = uow.GetRepository(); 28 | T item = repository.GetAll(id.GetIdentifierExpression()) 29 | .Include(repository.GetDbContext().GetIncludePaths(typeof(T))).FirstOrDefault(); 30 | 31 | if (item == null) 32 | return StatusCode(404); 33 | return Json(item); 34 | } 35 | } 36 | 37 | [HttpPost] 38 | [Route("DynamicQuery")] 39 | public IActionResult DynamicQuery([FromBody] SelectDto selectDto) 40 | { 41 | using (var uow = new UnitOfWork()) 42 | { 43 | var repository = uow.GetRepository(); 44 | return Json(repository.GetAll(selectDto.GetExpression()) 45 | .Include(repository.GetDbContext().GetIncludePaths(typeof(T))).ToList()); 46 | } 47 | } 48 | 49 | 50 | [HttpPut] 51 | public IActionResult Put([FromBody]T item) 52 | { 53 | using (var uow = new UnitOfWork()) 54 | { 55 | uow.GetRepository().Add(item); 56 | if (uow.SaveChanges() > 0) 57 | return Json(item); 58 | return StatusCode(500); 59 | } 60 | } 61 | 62 | [HttpDelete] 63 | [Route("{id}")] 64 | public IActionResult Delete(long id) 65 | { 66 | using (var uow = new UnitOfWork()) 67 | { 68 | T item = uow.GetRepository().Get(id.GetIdentifierExpression()); 69 | if (item == null) 70 | return StatusCode(404); 71 | 72 | uow.GetRepository().Delete(item); 73 | return StatusCode(uow.SaveChanges() > 0 ? 200 : 500); 74 | } 75 | } 76 | 77 | [HttpPost] 78 | [Route("{id}")] 79 | public IActionResult Update(long id, [FromBody] T updateItem) 80 | { 81 | using (var uow = new UnitOfWork()) 82 | { 83 | T item = uow.GetRepository().Get(id.GetIdentifierExpression()); 84 | if (item == null) 85 | return StatusCode(404); 86 | 87 | ObjectMapper.MapExclude(item, updateItem, new string[] { typeof(T).GetIdentifierColumnName() }); 88 | uow.GetRepository().Update(item); 89 | return StatusCode(uow.SaveChanges() > 0 ? 200 : 500); 90 | } 91 | } 92 | 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /DMicroservices/Base/Identity/IdentityFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Microsoft.AspNetCore.Mvc.Filters; 5 | 6 | namespace DMicroservices.Base.Identity 7 | { 8 | public abstract class IdentityFilter : ActionFilterAttribute, IAuthorizationFilter 9 | { 10 | public virtual void OnAuthorization(AuthorizationFilterContext context) 11 | { 12 | 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /DMicroservices/DMicroservices.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1 5 | true 6 | https://github.com/detayteknoloji/dmicroservices 7 | Serhat Boyraz 8 | Detaysoft 9 | 3.1.102 10 | LICENSE 11 | Library 12 | true 13 | 3.1.102 14 | 3.1.102 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | True 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /DMicroservices/DataAccess/Cache/MemoryCacheManager.cs: -------------------------------------------------------------------------------- 1 | using DMicroservices.Utils.Logger; 2 | using MessagePack; 3 | using Microsoft.Extensions.Caching.Memory; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text.RegularExpressions; 8 | using System.Threading; 9 | using Microsoft.Extensions.Options; 10 | using System.Collections; 11 | using System.Reflection; 12 | 13 | namespace DMicroservices.DataAccess.Cache 14 | { 15 | public class MemoryCacheManager 16 | { 17 | private IMemoryCache _memoryCache; 18 | private bool _memoryCacheDisabled = false; 19 | #region Singleton Section 20 | 21 | private static readonly Lazy _instance = new Lazy(() => new MemoryCacheManager()); 22 | 23 | protected MemoryCacheManager() 24 | { 25 | 26 | _memoryCache = new MemoryCache(new MemoryDistributedCacheOptions() 27 | { 28 | SizeLimit = null 29 | }); 30 | } 31 | 32 | public static MemoryCacheManager Instance => _instance.Value; 33 | #endregion 34 | 35 | /// 36 | /// Bellekte tutulan veriyi getirir. 37 | /// 38 | /// 39 | /// 40 | public string Get(string key) 41 | { 42 | if (_memoryCacheDisabled) 43 | return null; 44 | return _memoryCache.Get(key)?.ToString(); 45 | } 46 | 47 | /// 48 | /// Önbellekte tutulan veriyi siler. 49 | /// 50 | /// 51 | public bool DeleteByKey(string key) 52 | { 53 | if (_memoryCacheDisabled) 54 | return true; 55 | 56 | _memoryCache.Remove(key); 57 | return true; 58 | } 59 | 60 | /// 61 | /// Önbellekte tutulan verileri key benzerliğine göre siler. 62 | /// 63 | /// 64 | public bool DeleteByKeyLike(string key) 65 | { 66 | 67 | if (_memoryCacheDisabled) 68 | return true; 69 | 70 | foreach (var keyItem in GetAllKeys()) 71 | { 72 | if (keyItem.StartsWith(key)) 73 | _memoryCache.Remove(keyItem); 74 | } 75 | 76 | return true; 77 | } 78 | 79 | /// 80 | /// Tüm listeyi temizler 81 | /// 82 | public bool Clear() 83 | { 84 | if (_memoryCacheDisabled) 85 | return true; 86 | 87 | foreach (var key in GetAllKeys()) 88 | { 89 | _memoryCache.Remove(key); 90 | } 91 | 92 | return true; 93 | } 94 | 95 | /// 96 | /// Önbellekte veriyi, verilmişse istenilen süre kadar tutar 97 | /// 98 | /// 99 | /// 100 | /// 101 | public bool Set(string key, string value, TimeSpan? expireTime = null) 102 | { 103 | if (_memoryCacheDisabled) 104 | return true; 105 | 106 | if (expireTime.HasValue) 107 | _memoryCache.Set(key, value, expireTime.Value); 108 | else 109 | _memoryCache.Set(key, value); 110 | 111 | return true; 112 | } 113 | 114 | /// 115 | /// Önbellekte veriyi, verilmişse istenilen süre kadar tutar 116 | /// 117 | /// 118 | /// 119 | /// 120 | public bool Set(Dictionary bulkInsertList) 121 | { 122 | if (_memoryCacheDisabled) 123 | return true; 124 | 125 | foreach (var (key, value) in bulkInsertList) 126 | { 127 | _memoryCache.Set(key, value); 128 | } 129 | 130 | return true; 131 | } 132 | 133 | /// 134 | /// Önbellekte byte[] tipinde veriyi tutar. 135 | /// 136 | /// 137 | /// 138 | public bool SetSerializeBytes(string key, T value, TimeSpan? expireTime = null) 139 | { 140 | if (_memoryCacheDisabled) 141 | return true; 142 | 143 | if (expireTime.HasValue) 144 | _memoryCache.Set(key, value, expireTime.Value); 145 | else 146 | _memoryCache.Set(key, value); 147 | 148 | 149 | return false; 150 | } 151 | 152 | /// 153 | /// Önbellekte tutulan byte[] tipinde veriyi döner. 154 | /// 155 | /// 156 | public T GetDeserializeBytes(string key) 157 | { 158 | if (_memoryCacheDisabled) 159 | return default; 160 | 161 | return _memoryCache.Get(key); 162 | } 163 | 164 | /// 165 | /// Anahtara göre var olup olmadığını döner 166 | /// 167 | /// 168 | public bool Exists(string key) 169 | { 170 | if (_memoryCacheDisabled) 171 | return false; 172 | 173 | return _memoryCache.Get(key) != null; 174 | } 175 | 176 | /// 177 | /// Anahtara göre var olun önbelleği döner 178 | /// 179 | /// 180 | public bool GetIfExists(string key, out string obj) 181 | { 182 | if (_memoryCacheDisabled) 183 | { 184 | obj = null; 185 | return false; 186 | } 187 | 188 | obj = _memoryCache.Get(key)?.ToString(); 189 | return obj != null; 190 | } 191 | 192 | /// 193 | /// Anahtara göre var olun önbelleği döner 194 | /// 195 | /// 196 | public bool GetIfExists(string key, out T obj) where T : class 197 | { 198 | if (_memoryCacheDisabled) 199 | { 200 | obj = null; 201 | return false; 202 | } 203 | 204 | var memoryCacheData = _memoryCache.Get(key); 205 | 206 | obj = (T)memoryCacheData; 207 | return memoryCacheData != null; 208 | } 209 | 210 | public List GetAllKeys() 211 | { 212 | if (_memoryCacheDisabled) 213 | { 214 | return null; 215 | } 216 | 217 | var field = typeof(MemoryCache).GetProperty("EntriesCollection", BindingFlags.NonPublic | BindingFlags.Instance); 218 | var collection = field.GetValue(_memoryCache) as ICollection; 219 | var items = new List(); 220 | if (collection != null) 221 | foreach (var item in collection) 222 | { 223 | var methodInfo = item.GetType().GetProperty("Key"); 224 | var val = methodInfo.GetValue(item); 225 | items.Add(val.ToString()); 226 | } 227 | 228 | return items; 229 | } 230 | 231 | public void DisableCache() 232 | { 233 | _memoryCacheDisabled = true; 234 | } 235 | public void EnableCache() 236 | { 237 | _memoryCacheDisabled = false; 238 | } 239 | } 240 | } 241 | -------------------------------------------------------------------------------- /DMicroservices/DataAccess/DynamicQuery/Enum/SortTypeEnum.cs: -------------------------------------------------------------------------------- 1 | namespace DMicroservices.DataAccess.DynamicQuery.Enum 2 | { 3 | /// 4 | /// Sıralama tipi 5 | /// 6 | public enum SortTypeEnum 7 | { 8 | /// 9 | /// Artan 10 | /// 11 | ASC, 12 | 13 | /// 14 | /// Azalan 15 | /// 16 | DESC 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /DMicroservices/DataAccess/DynamicQuery/Enum/TypePropertyEnum.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace DMicroservices.DataAccess.DynamicQuery.Enum 7 | { 8 | public enum TypePropertyEnum 9 | { 10 | Byte =0, 11 | Sbyte =1, 12 | Short = 2, 13 | Ushort = 3, 14 | Int32 = 4, 15 | Uint = 5, 16 | Long = 6, 17 | Ulong = 7, 18 | Float = 8, 19 | Double = 9, 20 | Decimal = 10, 21 | Char = 11, 22 | Boolean = 12, 23 | Object = 13, 24 | String = 14, 25 | DateTime =15, 26 | DateTimeNullable= 16, 27 | Int32Nullable= 17, 28 | ByteNullable= 18 29 | 30 | 31 | 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /DMicroservices/DataAccess/DynamicQuery/FilterCompareTypesItem.cs: -------------------------------------------------------------------------------- 1 | namespace DMicroservices.DataAccess.DynamicQuery 2 | { 3 | public class FilterCompareTypesItem 4 | { 5 | /// 6 | /// Mantıksal grup ismi. 7 | /// 8 | public string Group { get; set; } 9 | 10 | /// 11 | /// Grubun AND/OR şeklinde birleştirilmesi için AND ve ya OR bağlacı 12 | /// AND/OR 13 | /// 14 | public string Type { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /DMicroservices/DataAccess/DynamicQuery/FilterItemDto.cs: -------------------------------------------------------------------------------- 1 | namespace DMicroservices.DataAccess.DynamicQuery 2 | { 3 | /// 4 | /// Filtreleme yapmak için rest tarafından gönderilen veri ögesi 5 | /// 6 | public class FilterItemDto 7 | { 8 | /// 9 | /// Filtreleme yapılması için özellik adı. 10 | /// 11 | public string PropertyName { get; set; } 12 | 13 | /// 14 | /// Filtreleme yapılacak işlem
15 | /// "EQ" ->equals
16 | /// "IN" ->in
17 | /// "CT" ->contains
18 | /// "LT" ->less than
19 | /// "GT" ->grater than
20 | ///
21 | public string Operation { get; set; } 22 | 23 | /// 24 | /// Filtreleme yapılacak value 25 | /// 26 | public string PropertyValue { get; set; } 27 | 28 | /// 29 | /// Karşılaştırma yapılırken PropertyName tarafında uygulanacak olan metod.
30 | /// "ToLower" -> PropertyName.ToLower()
31 | /// "ToUpper" -> PropertyName.ToUpper()
32 | ///
33 | public string ConversionMethodName { get; set; } 34 | 35 | /// 36 | /// Mantıksal grup ismi. 37 | /// Gruplamak / AND or işlemini gruba uygulamak için kullanılır. 38 | /// 39 | public string Group { get; set; } 40 | 41 | /// 42 | /// Bir kolon birden fazla tabloda kullanılıyorsa ve bu kolonun iki tabloda birden aynı filtre ile sorgu çekilmesi gerekmiyorsa bu alan 43 | /// BNT_<TABLO ADI> şeklinde belirtilir. 44 | /// 45 | public string TableObject { get; set; } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /DMicroservices/DataAccess/DynamicQuery/OrderItemDto.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace DMicroservices.DataAccess.DynamicQuery 3 | { 4 | /// 5 | /// Sıralama yapmak için gerekli nesne 6 | /// 7 | public class OrderItemDto 8 | { 9 | /// 10 | /// Filtreleme yapılması için özellik adı. 11 | /// 12 | public string Column { get; set; } 13 | 14 | /// 15 | /// Descending olarak sırala? 16 | /// 17 | public bool Descending { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /DMicroservices/DataAccess/DynamicQuery/SortItemDto.cs: -------------------------------------------------------------------------------- 1 | using DMicroservices.DataAccess.DynamicQuery.Enum; 2 | 3 | namespace DMicroservices.DataAccess.DynamicQuery 4 | { 5 | public class SortItemDto 6 | { 7 | /// 8 | /// Sıralama yapılacak olan özellik. 9 | /// 10 | public string PropertyName { get; set; } 11 | 12 | /// 13 | /// Sıralama Türü 14 | /// 15 | public SortTypeEnum SortType { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /DMicroservices/DataAccess/ElasticSearch/ElasticHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Nest; 6 | 7 | namespace DMicroservices.DataAccess.ElasticSearch 8 | { 9 | public class ElasticHelper : IElasticRepository where T : class 10 | { 11 | #region Singleton Section 12 | 13 | private static readonly Lazy> _instance = new Lazy>(() => new ElasticHelper()); 14 | 15 | private ElasticHelper() 16 | { 17 | } 18 | 19 | public static ElasticHelper Instance => _instance.Value; 20 | 21 | #endregion 22 | 23 | #region Members 24 | 25 | private ConnectionSettings _connectionSettings; 26 | 27 | private ElasticClient _elasticClient; 28 | 29 | #endregion 30 | 31 | #region Property 32 | private ConnectionSettings ConnectionSettings 33 | { 34 | get 35 | { 36 | if (_connectionSettings == null) 37 | { 38 | string elasticUri = Environment.GetEnvironmentVariable("ELASTIC_URI"); 39 | 40 | if (string.IsNullOrEmpty(elasticUri)) 41 | throw new ArgumentNullException($"ELASTIC_URI environment variable can not be empty"); 42 | 43 | _connectionSettings = new ConnectionSettings(new Uri(elasticUri)); 44 | } 45 | 46 | return _connectionSettings; 47 | } 48 | } 49 | 50 | private ElasticClient ElasticClient 51 | { 52 | get 53 | { 54 | if (_elasticClient == null) 55 | _elasticClient = new ElasticClient(ConnectionSettings); 56 | return _elasticClient; 57 | } 58 | } 59 | 60 | #endregion 61 | 62 | #region Methods 63 | 64 | /// 65 | /// Elasticsearch'e verilen modeli indexler. 66 | /// 67 | /// 68 | /// 69 | /// 70 | public IndexResponse AddIndex(T model, string indexName = null) 71 | { 72 | return ElasticClient.Index(model, p => p.Index(indexName?.ToLower() ?? typeof(T).Name.ToLower())); 73 | } 74 | 75 | /// 76 | /// Elasticsearch'e verilen modeli asenkron olarak indexler. 77 | /// 78 | /// 79 | /// 80 | /// 81 | public Task AddIndexAsync(T model, string indexName = null) 82 | { 83 | return ElasticClient.IndexAsync(model, p => p.Index(indexName?.ToLower() ?? typeof(T).Name.ToLower())); 84 | } 85 | 86 | /// 87 | /// Elasticsearch'e verilen model listesini ekler. 88 | /// 89 | /// 90 | /// 91 | /// 92 | public BulkResponse BulkIndexList(List model, string indexName = null) 93 | { 94 | if (!model.Any()) 95 | throw new ArgumentNullException($"model cannot be null!"); 96 | 97 | return ElasticClient.Bulk(p => p 98 | .Index(indexName?.ToLower() ?? typeof(T).Name.ToLower()) 99 | .IndexMany(model) 100 | ); 101 | } 102 | 103 | /// 104 | /// Elasticsearch'e verilen model listesini asenkron olarak ekler. 105 | /// 106 | /// 107 | /// 108 | /// 109 | public Task BulkIndexListAsync(List model, string indexName = null) 110 | { 111 | if (!model.Any()) 112 | throw new ArgumentNullException($"model cannot be null!"); 113 | 114 | return ElasticClient.BulkAsync(p => p 115 | .Index(indexName?.ToLower() ?? typeof(T).Name.ToLower()) 116 | .IndexMany(model) 117 | ); 118 | } 119 | 120 | /// 121 | /// Elasticsearch'e verilen model listesini ekler. 122 | /// 123 | /// 124 | /// Yeniden denemeden önce beklenilecek süre 125 | /// Hata alındığında deneme sayısı 126 | /// Toplu istek başı gönderilecek öge sayısı 127 | /// 128 | /// 129 | public BulkAllObservable BulkAllObservable(List model, int backOffTime, int backOffRetries, int size, string indexName = null) 130 | { 131 | if (!model.Any()) 132 | throw new ArgumentNullException($"model cannot be null!"); 133 | 134 | return ElasticClient.BulkAll(model, b => b 135 | .Index(indexName?.ToLower() ?? typeof(T).Name.ToLower()) 136 | .BackOffTime(backOffTime) 137 | .BackOffRetries(backOffRetries) 138 | .MaxDegreeOfParallelism(Environment.ProcessorCount) 139 | .Size(size) 140 | ); 141 | } 142 | 143 | /// 144 | /// Verilen index ismine göre gönderilen idyi siler. 145 | /// 146 | /// 147 | /// 148 | /// 149 | public DeleteResponse DeleteIndex(string indexName, string id) 150 | { 151 | if (string.IsNullOrEmpty(indexName) || id == null) 152 | { 153 | throw new ArgumentNullException($"indexName and id cannot be null!"); 154 | } 155 | 156 | return ElasticClient.Delete(new DeleteRequest(indexName, id)); 157 | } 158 | 159 | /// 160 | /// Elasticsearchün kendi querysi ile gönderilen search querysi ile arama yapar. 161 | /// 162 | /// 163 | /// 164 | /// 165 | public ISearchResponse Search(Func, QueryContainer> searchTerms, string indexName = null) 166 | { 167 | if (indexName == null) 168 | indexName = typeof(T).Name; 169 | 170 | return ElasticClient.Search(p => p 171 | .Query(searchTerms) 172 | .Index(indexName.ToLower()) 173 | .Size(20) 174 | ); 175 | } 176 | 177 | #endregion 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /DMicroservices/DataAccess/ElasticSearch/IElasticRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | using Nest; 5 | 6 | namespace DMicroservices.DataAccess.ElasticSearch 7 | { 8 | public interface IElasticRepository where T : class 9 | { 10 | IndexResponse AddIndex(T model, string indexName = null); 11 | 12 | Task AddIndexAsync(T model, string indexName = null); 13 | 14 | BulkResponse BulkIndexList(List model, string indexName = null); 15 | 16 | Task BulkIndexListAsync(List model, string indexName = null); 17 | 18 | BulkAllObservable BulkAllObservable(List model, int backOffTime, int backOffRetries, int size, string indexName = null); 19 | 20 | DeleteResponse DeleteIndex(string indexName, string id); 21 | 22 | ISearchResponse Search(Func, QueryContainer> searchTerms, string indexName = null); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /DMicroservices/DataAccess/HealthCheck/DatabaseHealthCheck.cs: -------------------------------------------------------------------------------- 1 | using DMicroservices.DataAccess.Redis; 2 | using DMicroservices.DataAccess.UnitOfWork; 3 | using DMicroservices.Utils.Logger; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.Extensions.Diagnostics.HealthChecks; 6 | using System; 7 | using System.Threading; 8 | using System.Threading.Tasks; 9 | 10 | namespace DMicroservices.RabbitMq.Base 11 | { 12 | public class DatabaseHealthCheck : IHealthCheck 13 | { 14 | Type _dbContextType = null; 15 | public DatabaseHealthCheck(Type dbContextType) 16 | { 17 | _dbContextType = dbContextType; 18 | } 19 | 20 | public Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) 21 | { 22 | try 23 | { 24 | UnitOfWorkFactory.CreateUnitOfWork(_dbContextType).GetDbContext().Database.ExecuteSqlRaw("SELECT 1"); 25 | } 26 | catch (Exception e) 27 | { 28 | ElasticLogger.Instance.Error(e, $"Mysql Connection Lost"); 29 | return Task.FromResult(HealthCheckResult.Unhealthy("Mysql Connection Lost")); 30 | 31 | } 32 | 33 | return Task.FromResult(HealthCheckResult.Healthy()); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /DMicroservices/DataAccess/HealthCheck/RedisHealthCheck.cs: -------------------------------------------------------------------------------- 1 | using DMicroservices.DataAccess.Redis; 2 | using DMicroservices.DataAccess.UnitOfWork; 3 | using DMicroservices.Utils.Logger; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.Extensions.Diagnostics.HealthChecks; 6 | using System; 7 | using System.Threading; 8 | using System.Threading.Tasks; 9 | 10 | namespace DMicroservices.RabbitMq.Base 11 | { 12 | public class RedisHealthCheck : IHealthCheck 13 | { 14 | 15 | public Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) 16 | { 17 | try 18 | { 19 | RedisManager.Instance.Get("test"); 20 | } 21 | catch (Exception e) 22 | { 23 | ElasticLogger.Instance.Error(e, $"Redis Connection Lost"); 24 | return Task.FromResult(HealthCheckResult.Unhealthy("Redis Connection Lost")); 25 | 26 | } 27 | 28 | return Task.FromResult(HealthCheckResult.Healthy()); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /DMicroservices/DataAccess/History/HistoryCollectionModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace DMicroservices.DataAccess.History 7 | { 8 | public class HistoryCollectionModel 9 | { 10 | public string DatabaseName { get; set; } 11 | public string ObjectName { get; set; } 12 | public string ChangeType { get; set; } 13 | public string ChangedUser { get; set; } 14 | public object RowId { get; set; } 15 | public List Columns { get; set; } 16 | public string Hash { get; set; } 17 | public DateTime DateTime { get; set; } 18 | } 19 | 20 | public class HistoryTableColumnsModel 21 | { 22 | public string Name { get; set; } 23 | public object OldValue { get; set; } 24 | public object NewValue { get; set; } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /DMicroservices/DataAccess/MongoRepository/Base/MongoBaseModel.cs: -------------------------------------------------------------------------------- 1 | using MongoDB.Bson; 2 | using MongoDB.Bson.Serialization.Attributes; 3 | 4 | namespace DMicroservices.DataAccess.MongoRepository.Base 5 | { 6 | public abstract class MongoBaseModel 7 | { 8 | [BsonId] 9 | public ObjectId Id { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /DMicroservices/DataAccess/MongoRepository/Interfaces/IDatabaseSettings.cs: -------------------------------------------------------------------------------- 1 | namespace DMicroservices.DataAccess.MongoRepository.Interfaces 2 | { 3 | public interface IDatabaseSettings 4 | { 5 | string ConnectionString { get; set; } 6 | 7 | string DatabaseName { get; set; } 8 | 9 | string CollectionName { get; set; } 10 | 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /DMicroservices/DataAccess/MongoRepository/Interfaces/IMongoRepository.cs: -------------------------------------------------------------------------------- 1 | using DMicroservices.DataAccess.DynamicQuery.Enum; 2 | using MongoDB.Driver; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Linq.Expressions; 7 | 8 | namespace DMicroservices.DataAccess.MongoRepository.Interfaces 9 | { 10 | /// 11 | /// Model katmanımızda bulunan her T tipi için aşağıda tanımladığımız fonksiyonları gerçekleştirebilecek generic bir repository tanımlıyoruz. 12 | /// 13 | /// 14 | public interface IMongoRepository where T : class 15 | { 16 | /// 17 | /// Tüm veriyi getir. 18 | /// 19 | /// 20 | IQueryable GetAll(); 21 | 22 | /// 23 | /// Veriyi Where metodu ile getir. 24 | /// 25 | /// 26 | /// 27 | IQueryable GetAll(Expression> predicate); 28 | 29 | /// 30 | /// Verilen sorguya göre tablodaki sayıyı gönderir. 31 | /// 32 | /// 33 | /// 34 | int Count(); 35 | 36 | /// 37 | /// Verilen sorguya göre tablodaki sayıyı gönderir. 38 | /// 39 | /// 40 | /// 41 | int Count(Expression> predicate); 42 | 43 | /// 44 | /// İstenilen veriyi single olarak getirir. 45 | /// 46 | /// 47 | /// 48 | T Get(Expression> predicate); 49 | 50 | /// 51 | /// Getirilen veri üzerinde veri gelmeden kolonları seç. 52 | /// 53 | /// Veri kısıtlamaları 54 | /// Seçilecek kolonlar 55 | /// 56 | IQueryable SelectList(Expression> @where, Expression> @select); 57 | 58 | /// 59 | /// Verinin bir bölümünü getirir. 60 | /// 61 | /// neye gore gelsin? 62 | /// Veri nerden baslasin? 63 | /// Kac veri gelsin 64 | /// Neye gore sortlansin 65 | /// A|D (A->ascending | D->descending) 66 | /// 67 | IQueryable GetDataPart(Expression> where, Expression> sort, SortTypeEnum sortType, int skipCount, int takeCount); 68 | 69 | /// 70 | /// Entity ile sql sorgusu göndermek için kullanılır. 71 | /// 72 | /// Gönderilecek sql 73 | /// 74 | List SendSql(string sqlQuery); 75 | 76 | /// 77 | /// Verilen entityi ekle. 78 | /// 79 | /// 80 | bool Add(T entity); 81 | 82 | /// 83 | /// Verilen entity i güncelle. 84 | /// 85 | /// 86 | bool Update(T entity); 87 | 88 | /// 89 | /// predicate göre veriler düzenlenir. 90 | /// 91 | /// 92 | /// 93 | bool Update(Expression> predicate, T entity); 94 | 95 | /// 96 | /// Verilen entityi sil. 97 | /// 98 | /// 99 | bool Delete(T entity, bool forceDelete = false); 100 | 101 | /// 102 | /// predicate göre veriler silinir. 103 | /// 104 | /// 105 | /// 106 | bool Delete(Expression> predicate, bool forceDelete = false); 107 | 108 | bool Delete(FieldDefinition field, TField date); 109 | 110 | /// 111 | /// Aynı kayıt eklememek için objeyi kontrol ederek true veya false dönderir. 112 | /// 113 | /// 114 | /// 115 | /// 116 | bool Any(Expression> predicate); 117 | 118 | 119 | bool Truncate(); 120 | 121 | bool BulkInsert(List entityList); 122 | 123 | bool BulkDelete(Expression> predicate); 124 | 125 | bool AddAsync(T entity); 126 | 127 | bool UpdateAsync(Expression> predicate, T entity); 128 | 129 | bool BulkInsertAsync(List entityList); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /DMicroservices/DataAccess/MongoRepository/MongoRepositoryFactory.cs: -------------------------------------------------------------------------------- 1 | using DMicroservices.DataAccess.MongoRepository.Settings; 2 | 3 | namespace DMicroservices.DataAccess.MongoRepository 4 | { 5 | public static class MongoRepositoryFactory 6 | { 7 | public static MongoRepository CreateMongoRepository() where T : class 8 | { 9 | return new MongoRepository(); 10 | } 11 | 12 | public static MongoRepository CreateMongoRepository(DatabaseSettings databaseSettings) where T : class 13 | { 14 | return new MongoRepository(databaseSettings); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /DMicroservices/DataAccess/MongoRepository/Settings/DatabaseSettings.cs: -------------------------------------------------------------------------------- 1 | using DMicroservices.DataAccess.MongoRepository.Interfaces; 2 | 3 | namespace DMicroservices.DataAccess.MongoRepository.Settings 4 | { 5 | public class DatabaseSettings : IDatabaseSettings 6 | { 7 | public string ConnectionString { get; set; } 8 | 9 | public string DatabaseName { get; set; } 10 | 11 | public string CollectionName { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /DMicroservices/DataAccess/Redis/RedisList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using StackExchange.Redis; 6 | 7 | namespace DMicroservices.DataAccess.Redis 8 | { 9 | 10 | public class RedisList : IList 11 | { 12 | private static readonly string Domain = Environment.GetEnvironmentVariable("REDIS_URL"); 13 | private ConnectionMultiplexer Connection { get; set; } 14 | private IDatabase RedisDatabase { get; set; } 15 | 16 | private string _key; 17 | public RedisList(string key) 18 | { 19 | _key = key; 20 | 21 | ConfigurationOptions options = ConfigurationOptions.Parse(Domain); 22 | Connection = ConnectionMultiplexer.Connect(options); 23 | RedisDatabase = Connection.GetDatabase(); 24 | } 25 | private IDatabase GetRedisDb() 26 | { 27 | return Connection.GetDatabase(); 28 | } 29 | private byte[] Serialize(object obj) 30 | { 31 | return MessagePack.MessagePackSerializer.Serialize(obj, MessagePack.MessagePackSerializer.DefaultOptions.WithResolver(MessagePack.Resolvers.ContractlessStandardResolver.Instance)); 32 | } 33 | private T Deserialize(byte[] serialized) 34 | { 35 | return MessagePack.MessagePackSerializer.Deserialize(serialized, MessagePack.MessagePackSerializer.DefaultOptions.WithResolver(MessagePack.Resolvers.ContractlessStandardResolver.Instance)); 36 | } 37 | public void Insert(int index, T item) 38 | { 39 | var db = GetRedisDb(); 40 | var before = db.ListGetByIndex(_key, index); 41 | db.ListInsertBefore(_key, before, Serialize(item)); 42 | } 43 | public void RemoveAt(int index) 44 | { 45 | var db = GetRedisDb(); 46 | var value = db.ListGetByIndex(_key, index); 47 | if (!value.IsNull) 48 | { 49 | db.ListRemove(_key, value); 50 | } 51 | } 52 | public T this[int index] 53 | { 54 | get 55 | { 56 | var value = GetRedisDb().ListGetByIndex(_key, index); 57 | return Deserialize(value); 58 | } 59 | set 60 | { 61 | Insert(index, value); 62 | } 63 | } 64 | public void Add(T item) 65 | { 66 | GetRedisDb().ListRightPush(_key, Serialize(item)); 67 | } 68 | public void Add(T item, TimeSpan expireTime) 69 | { 70 | GetRedisDb().ListRightPush(_key, Serialize(item)); 71 | 72 | GetRedisDb().KeyExpire(_key, expireTime); 73 | } 74 | 75 | public void AddRange(IEnumerable collection, TimeSpan? expireTime = null) 76 | { 77 | GetRedisDb().ListRightPush(_key, collection.Select(x => (RedisValue)Serialize(x)).ToArray()); 78 | 79 | if (expireTime == null) 80 | expireTime = new TimeSpan(0, 10, 0); 81 | 82 | GetRedisDb().KeyExpire(_key, expireTime); 83 | } 84 | 85 | public void AddRange(IEnumerable collection) 86 | { 87 | GetRedisDb().ListRightPush(_key, collection.Select(x => (RedisValue)Serialize(x)).ToArray()); 88 | } 89 | 90 | public void Clear() 91 | { 92 | GetRedisDb().KeyDelete(_key); 93 | } 94 | public bool Contains(T item) 95 | { 96 | for (int i = 0; i < Count; i++) 97 | { 98 | if (GetRedisDb().ListGetByIndex(_key, i).ToString().Equals(Serialize(item))) 99 | { 100 | return true; 101 | } 102 | } 103 | return false; 104 | } 105 | public void CopyTo(T[] array, int arrayIndex) 106 | { 107 | var range = GetRedisDb().ListRange(_key); 108 | for (var i = 0; i < range.Length; i++) 109 | { 110 | array[i] = Deserialize(range[i]); 111 | } 112 | } 113 | public int IndexOf(T item) 114 | { 115 | for (int i = 0; i < Count; i++) 116 | { 117 | if (GetRedisDb().ListGetByIndex(_key, i).ToString().Equals(Serialize(item))) 118 | { 119 | return i; 120 | } 121 | } 122 | return -1; 123 | } 124 | public int Count 125 | { 126 | get { return (int)GetRedisDb().ListLength(_key); } 127 | } 128 | public bool IsReadOnly 129 | { 130 | get { return false; } 131 | } 132 | public bool Remove(T item) 133 | { 134 | return GetRedisDb().ListRemove(_key, Serialize(item)) > 0; 135 | } 136 | public IEnumerator GetEnumerator() 137 | { 138 | for (int i = 0; i < this.Count; i++) 139 | { 140 | yield return Deserialize(GetRedisDb().ListGetByIndex(_key, i)); 141 | } 142 | } 143 | System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 144 | { 145 | for (int i = 0; i < this.Count; i++) 146 | { 147 | yield return Deserialize(GetRedisDb().ListGetByIndex(_key, i)); 148 | } 149 | } 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /DMicroservices/DataAccess/Repository/FilteredReadonlyRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using System.Reflection; 6 | using DMicroservices.DataAccess.History; 7 | using DMicroservices.Utils.Extensions; 8 | using Microsoft.EntityFrameworkCore; 9 | using Microsoft.EntityFrameworkCore.ChangeTracking; 10 | 11 | namespace DMicroservices.DataAccess.Repository 12 | { 13 | /// 14 | /// EntityFramework için hazırlıyor olduğumuz bu repositoriyi daha önceden tasarladığımız generic repositorimiz olan IRepository arayüzünü implemente ederek tasarladık. 15 | /// Bu şekilde tasarlamamızın ana sebebi ise veritabanına independent(bağımsız) bir durumda kalabilmek. 16 | /// 17 | /// 18 | public class FilteredReadonlyRepository : IRepository where T : class 19 | { 20 | private readonly DbContext DbContext; 21 | private readonly DbSet DbSet; 22 | 23 | public string FilterColumnName { get; set; } 24 | public object FilterColumnValue { get; set; } 25 | 26 | private PropertyInfo FilterProperty; 27 | /// 28 | /// Repository instance ı başlatırç 29 | /// 30 | /// Veritabanı bağlantı nesnesi 31 | /// 32 | /// 33 | public FilteredReadonlyRepository(DbContext dbContext, string filterColumnName, object filterValue) 34 | { 35 | DbContext = dbContext; 36 | DbSet = dbContext.Set(); 37 | FilterColumnName = filterColumnName; 38 | FilterColumnValue = filterValue; 39 | FilterProperty = typeof(T).GetProperty(FilterColumnName); 40 | } 41 | 42 | public void Add(T entity) 43 | { 44 | throw new NotImplementedException("This repository is read-only."); 45 | } 46 | 47 | public void BulkInsert(List entityList) 48 | { 49 | throw new NotImplementedException("This repository is read-only."); 50 | } 51 | 52 | /// 53 | /// Aynı kayıt eklememek için objeyi kontrol ederek true veya false dönderir. 54 | /// 55 | /// 56 | /// 57 | /// 58 | public bool Any(Expression> predicate) 59 | { 60 | return DbSet.Where(GetFilterExpression()).Any(predicate); 61 | } 62 | 63 | public DbContext GetDbContext() 64 | { 65 | return DbContext; 66 | } 67 | 68 | public List GetIncludePaths() 69 | { 70 | return DbContext.GetIncludePaths(typeof(T)).ToList(); 71 | } 72 | 73 | public int Count() 74 | { 75 | return Count(arg => true); 76 | } 77 | 78 | public int Count(Expression> predicate) 79 | { 80 | IQueryable iQueryable = DbSet.Where(GetFilterExpression()) 81 | .Where(predicate); 82 | return iQueryable.Count(); 83 | } 84 | 85 | public void Delete(T entity, bool forceDelete = false) 86 | { 87 | throw new NotImplementedException("This repository is read-only."); 88 | } 89 | 90 | public void Delete(Expression> predicate, bool forceDelete = false) 91 | { 92 | throw new NotImplementedException("This repository is read-only."); 93 | } 94 | 95 | public void BulkDelete(List entityList) 96 | { 97 | throw new NotImplementedException("This repository is read-only."); 98 | } 99 | 100 | public T Get(Expression> predicate) 101 | { 102 | IQueryable iQueryable = DbSet.Where(GetFilterExpression()) 103 | .Where(predicate); 104 | return iQueryable.ToList().FirstOrDefault(); 105 | } 106 | 107 | public TResult Get(Expression> predicate, Expression> @select) 108 | { 109 | IQueryable iQueryable = DbSet.Where(GetFilterExpression()) 110 | .Where(predicate); 111 | return iQueryable.Select(@select).FirstOrDefault(); 112 | } 113 | 114 | public T Get(Expression> predicate, List includePaths) 115 | { 116 | IQueryable iQueryable = DbSet 117 | .Where(predicate).Where(GetFilterExpression()).Include(includePaths); 118 | return iQueryable.ToList().FirstOrDefault(); 119 | } 120 | 121 | public IQueryable GetAll() 122 | { 123 | IQueryable iQueryable = DbSet.Where(GetFilterExpression()).Where(x => x != null); 124 | return iQueryable; 125 | } 126 | 127 | public IQueryable GetAll(System.Linq.Expressions.Expression> predicate) 128 | { 129 | IQueryable iQueryable = DbSet.Where(GetFilterExpression()) 130 | .Where(predicate); 131 | return iQueryable; 132 | } 133 | 134 | public IQueryable GetAll(System.Linq.Expressions.Expression> predicate, List includePaths) 135 | { 136 | IQueryable iQueryable = DbSet 137 | .Where(GetFilterExpression()).Where(predicate).Include(includePaths); 138 | return iQueryable; 139 | } 140 | 141 | public IQueryable SelectList(Expression> where, Expression> select) 142 | { 143 | throw new NotImplementedException(); 144 | } 145 | 146 | public IQueryable SelectList(Expression> @where, Expression> @select) 147 | { 148 | IQueryable iQueryable = DbSet 149 | .Where(GetFilterExpression()).Where(@where).Select(@select); 150 | return iQueryable; 151 | } 152 | 153 | public List SendSql(string sqlQuery) 154 | { 155 | throw new NotImplementedException(); 156 | } 157 | 158 | 159 | /// 160 | /// Clid ile yalıtabilmek için CLID ile ilgili expression oluşturur. 161 | /// 162 | /// 163 | private Expression> GetFilterExpression() 164 | { 165 | if (FilterProperty != null) 166 | { 167 | ParameterExpression argParams = Expression.Parameter(typeof(T), "x"); 168 | Expression filterProp = Expression.Property(argParams, FilterColumnName); 169 | ConstantExpression filterValue = Expression.Constant(FilterColumnValue); 170 | 171 | BinaryExpression filterExpression = Expression.Equal(filterProp, filterValue); 172 | return Expression.Lambda>(filterExpression, argParams); 173 | } 174 | 175 | return x => true; 176 | } 177 | 178 | 179 | /// 180 | /// Verilen veriyi context üzerinde günceller. 181 | /// 182 | /// Güncellenecek entity 183 | public void Update(T entity) 184 | { 185 | throw new NotImplementedException("This repository is read-only."); 186 | } 187 | 188 | public void UpdateProperties(T entity, params string[] changeProperties) 189 | { 190 | throw new NotImplementedException("This repository is read-only."); 191 | } 192 | 193 | public void Update(Expression> predicate, T entity) 194 | { 195 | throw new NotImplementedException("This repository is read-only."); 196 | } 197 | 198 | 199 | 200 | public int SendSqlScalar(string sqlQuery) 201 | { 202 | throw new NotImplementedException("This repository is read-only."); 203 | } 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /DMicroservices/DataAccess/Repository/IRepository.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Linq.Expressions; 6 | using DMicroservices.DataAccess.History; 7 | 8 | namespace DMicroservices.DataAccess.Repository 9 | { 10 | public interface IRepository where T : class 11 | { 12 | 13 | /// 14 | /// Tüm veriyi getir. 15 | /// 16 | /// 17 | IQueryable GetAll(); 18 | 19 | /// 20 | /// Veriyi Where metodu ile getir. 21 | /// 22 | /// 23 | /// 24 | IQueryable GetAll(Expression> predicate); 25 | 26 | /// 27 | /// Veriyi Where metodu ile getir. 28 | /// 29 | /// 30 | /// 31 | /// 32 | IQueryable GetAll(Expression> predicate, List includePaths); 33 | 34 | /// 35 | /// Verilen sorguya göre tablodaki sayıyı gönderir. 36 | /// 37 | /// 38 | /// 39 | int Count(); 40 | /// 41 | /// Verilen sorguya göre tablodaki sayıyı gönderir. 42 | /// 43 | /// 44 | /// 45 | int Count(Expression> predicate); 46 | 47 | /// 48 | /// İstenilen veriyi single olarak getirir. 49 | /// 50 | /// 51 | /// 52 | T Get(Expression> predicate); 53 | 54 | /// 55 | /// İstenilen veriyi single olarak getirir. 56 | /// 57 | /// 58 | /// 59 | TResult Get(Expression> predicate, Expression> @select); 60 | 61 | /// 62 | /// İstenilen veriyi single olarak getirir. 63 | /// 64 | /// 65 | T Get(Expression> predicate, List includePaths); 66 | 67 | /// 68 | /// Getirilen veri üzerinde veri gelmeden kolonları seç. 69 | /// 70 | /// Veri kısıtlamaları 71 | /// Seçilecek kolonlar 72 | /// 73 | IQueryable SelectList(Expression> @where, Expression> @select); 74 | 75 | /// 76 | /// Getirilen veri üzerinde veri gelmeden kolonları seç. 77 | /// 78 | /// Veri kısıtlamaları 79 | /// Seçilecek kolonlar 80 | /// 81 | IQueryable SelectList(Expression> @where, Expression> @select); 82 | 83 | /// 84 | /// Entity ile sql sorgusu göndermek için kullanılır. 85 | /// 86 | /// Gönderilecek sql 87 | /// 88 | List SendSql(string sqlQuery); 89 | 90 | /// 91 | /// Execute sql query. Return affected rows. 92 | /// 93 | /// 94 | /// 95 | int SendSqlScalar(string sqlQuery); 96 | 97 | /// 98 | /// Verilen entityi ekle. 99 | /// 100 | /// 101 | void Add(T entity); 102 | 103 | /// 104 | /// Verilen entityi ekle. 105 | /// 106 | /// 107 | void BulkInsert(List entityList); 108 | 109 | /// 110 | /// Verilen entity i güncelle. 111 | /// 112 | /// 113 | void Update(T entity); 114 | 115 | /// 116 | /// Verilen entity i güncelle. 117 | /// 118 | /// 119 | void UpdateProperties(T entity,params string[] changeProperties); 120 | 121 | /// 122 | /// predicate göre veriler düzenlenir. 123 | /// 124 | /// 125 | /// 126 | void Update(Expression> predicate, T entity); 127 | 128 | /// 129 | /// Verilen entityi sil. 130 | /// 131 | /// 132 | void Delete(T entity, bool forceDelete = false); 133 | 134 | /// 135 | /// predicate göre veriler silinir. 136 | /// 137 | /// 138 | void Delete(Expression> predicate, bool forceDelete = false); 139 | 140 | /// 141 | /// Verilen entityi sil. 142 | /// 143 | /// 144 | void BulkDelete(List entityList); 145 | 146 | /// 147 | /// Aynı kayıt eklememek için objeyi kontrol ederek true veya false dönderir. 148 | /// 149 | /// 150 | /// 151 | /// 152 | bool Any(Expression> predicate); 153 | 154 | /// 155 | /// DbContext i verir. 156 | /// 157 | /// 158 | DbContext GetDbContext(); 159 | 160 | List GetIncludePaths(); 161 | 162 | 163 | 164 | } 165 | } 166 | 167 | 168 | -------------------------------------------------------------------------------- /DMicroservices/DataAccess/Repository/ReadonlyRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Linq.Expressions; 6 | using DMicroservices.DataAccess.History; 7 | using DMicroservices.Utils.Extensions; 8 | using Microsoft.EntityFrameworkCore; 9 | using Microsoft.EntityFrameworkCore.ChangeTracking; 10 | 11 | namespace DMicroservices.DataAccess.Repository 12 | { 13 | /// 14 | /// EntityFramework için hazırlıyor olduğumuz bu repositoriyi daha önceden tasarladığımız generic repositorimiz olan IRepository arayüzünü implemente ederek tasarladık. 15 | /// Bu şekilde tasarlamamızın ana sebebi ise veritabanına independent(bağımsız) bir durumda kalabilmek. 16 | /// 17 | /// 18 | public class ReadonlyRepository : IRepository where T : class 19 | { 20 | private readonly DbContext DbContext; 21 | private readonly DbSet DbSet; 22 | 23 | /// 24 | /// Repository instance ı başlatırç 25 | /// 26 | /// Veritabanı bağlantı nesnesi 27 | public ReadonlyRepository(DbContext dbContext) 28 | { 29 | DbContext = dbContext; 30 | DbSet = dbContext.Set(); 31 | } 32 | 33 | public void Add(T entity) 34 | { 35 | throw new NotImplementedException("This repository is read-only."); 36 | } 37 | 38 | public void BulkInsert(List entityList) 39 | { 40 | throw new NotImplementedException("This repository is read-only."); 41 | } 42 | 43 | /// 44 | /// Aynı kayıt eklememek için objeyi kontrol ederek true veya false dönderir. 45 | /// 46 | /// 47 | /// 48 | /// 49 | public bool Any(Expression> predicate) 50 | { 51 | return DbSet.Any(predicate); 52 | } 53 | 54 | public DbContext GetDbContext() 55 | { 56 | return DbContext; 57 | } 58 | 59 | public List GetIncludePaths() 60 | { 61 | return DbContext.GetIncludePaths(typeof(T)).ToList(); 62 | } 63 | 64 | public int Count() 65 | { 66 | return Count(arg => true); 67 | } 68 | 69 | public int Count(Expression> predicate) 70 | { 71 | IQueryable iQueryable = DbSet 72 | .Where(predicate); 73 | return iQueryable.Count(); 74 | } 75 | 76 | public void Delete(T entity, bool forceDelete = false) 77 | { 78 | throw new NotImplementedException("This repository is read-only."); 79 | } 80 | 81 | public void Delete(Expression> predicate, bool forceDelete = false) 82 | { 83 | throw new NotImplementedException("This repository is read-only."); 84 | } 85 | public void BulkDelete(List entityList) 86 | { 87 | throw new NotImplementedException("This repository is read-only."); 88 | } 89 | 90 | public T Get(Expression> predicate) 91 | { 92 | IQueryable iQueryable = DbSet 93 | .Where(predicate); 94 | return iQueryable.ToList().FirstOrDefault(); 95 | } 96 | 97 | public TResult Get(Expression> predicate, Expression> @select) 98 | { 99 | IQueryable iQueryable = DbSet 100 | .Where(predicate); 101 | return iQueryable.Select(@select).FirstOrDefault(); 102 | } 103 | 104 | public T Get(Expression> predicate, List includePaths) 105 | { 106 | IQueryable iQueryable = DbSet 107 | .Where(predicate).Include(includePaths); 108 | return iQueryable.ToList().FirstOrDefault(); 109 | } 110 | 111 | public IQueryable GetAll() 112 | { 113 | IQueryable iQueryable = DbSet.Where(x => x != null); 114 | return iQueryable; 115 | } 116 | 117 | public IQueryable GetAll(System.Linq.Expressions.Expression> predicate) 118 | { 119 | IQueryable iQueryable = DbSet 120 | .Where(predicate); 121 | return iQueryable; 122 | } 123 | 124 | public IQueryable GetAll(System.Linq.Expressions.Expression> predicate, List includePaths) 125 | { 126 | IQueryable iQueryable = DbSet 127 | .Where(predicate).Include(includePaths); 128 | return iQueryable; 129 | } 130 | 131 | public IQueryable SelectList(Expression> where, Expression> select) 132 | { 133 | throw new NotImplementedException(); 134 | } 135 | 136 | public IQueryable SelectList(Expression> @where, Expression> @select) 137 | { 138 | IQueryable iQueryable = DbSet 139 | .Where(@where).Select(@select); 140 | return iQueryable; 141 | } 142 | 143 | public List SendSql(string sqlQuery) 144 | { 145 | throw new NotImplementedException(); 146 | } 147 | 148 | 149 | /// 150 | /// Verilen veriyi context üzerinde günceller. 151 | /// 152 | /// Güncellenecek entity 153 | public void Update(T entity) 154 | { 155 | throw new NotImplementedException("This repository is read-only."); 156 | } 157 | 158 | public void UpdateProperties(T entity, params string[] changeProperties) 159 | { 160 | throw new NotImplementedException("This repository is read-only."); 161 | } 162 | 163 | public void Update(Expression> predicate, T entity) 164 | { 165 | throw new NotImplementedException("This repository is read-only."); 166 | } 167 | 168 | public int SendSqlScalar(string sqlQuery) 169 | { 170 | throw new NotImplementedException("This repository is read-only."); 171 | } 172 | 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /DMicroservices/DataAccess/Repository/Repository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using System.Reflection; 6 | using DMicroservices.Base.Attributes; 7 | using DMicroservices.DataAccess.History; 8 | using DMicroservices.Utils.Extensions; 9 | using Microsoft.EntityFrameworkCore; 10 | using Microsoft.EntityFrameworkCore.ChangeTracking; 11 | using Microsoft.EntityFrameworkCore.Metadata.Internal; 12 | 13 | namespace DMicroservices.DataAccess.Repository 14 | { 15 | /// 16 | /// EntityFramework için hazırlıyor olduğumuz bu repositoriyi daha önceden tasarladığımız generic repositorimiz olan IRepository arayüzünü implemente ederek tasarladık. 17 | /// Bu şekilde tasarlamamızın ana sebebi ise veritabanına independent(bağımsız) bir durumda kalabilmek. 18 | /// 19 | /// 20 | public class Repository : IRepository where T : class 21 | { 22 | private readonly DbContext DbContext; 23 | private readonly DbSet DbSet; 24 | 25 | /// 26 | /// Repository instance ı başlatırç 27 | /// 28 | /// Veritabanı bağlantı nesnesi 29 | public Repository(DbContext dbContext) 30 | { 31 | DbContext = dbContext; 32 | DbSet = dbContext.Set(); 33 | } 34 | 35 | public void Add(T entity) 36 | { 37 | DbSet.Add(entity); 38 | } 39 | 40 | public void BulkInsert(List entityList) 41 | { 42 | foreach (var entity in entityList) 43 | { 44 | DbSet.Add(entity); 45 | } 46 | } 47 | 48 | /// 49 | /// Aynı kayıt eklememek için objeyi kontrol ederek true veya false dönderir. 50 | /// 51 | /// 52 | /// 53 | /// 54 | public bool Any(Expression> predicate) 55 | { 56 | return DbSet.Any(predicate); 57 | } 58 | 59 | /// 60 | /// Aynı kayıt eklememek için objeyi varsa alt ilişkisiyle birlikte kontrol ederek true veya false dönderir. 61 | /// 62 | /// 63 | /// Sorgu 64 | /// Join nesnelerinin classı 65 | /// 66 | public bool Any(Expression> predicate, List includePaths) 67 | { 68 | return DbSet.Include(includePaths).Any(predicate); 69 | } 70 | 71 | public DbContext GetDbContext() 72 | { 73 | return DbContext; 74 | } 75 | 76 | public List GetIncludePaths() 77 | { 78 | return DbContext.GetIncludePaths(typeof(T)).ToList(); 79 | } 80 | 81 | public int Count() 82 | { 83 | return Count(arg => true); 84 | } 85 | 86 | public int Count(Expression> predicate) 87 | { 88 | IQueryable iQueryable = DbSet 89 | .Where(predicate); 90 | return iQueryable.Count(); 91 | } 92 | 93 | public int Count(Expression> predicate, List includePaths) 94 | { 95 | IQueryable iQueryable = DbSet.Include(includePaths) 96 | .Where(predicate); 97 | return iQueryable.Count(); 98 | } 99 | 100 | public void Delete(T entity, bool forceDelete = false) 101 | { 102 | // Önce entity'nin state'ini kontrol etmeliyiz. 103 | EntityEntry dbEntityEntry = DbContext.Entry(entity); 104 | 105 | if (dbEntityEntry.State != EntityState.Deleted) 106 | { 107 | dbEntityEntry.State = EntityState.Deleted; 108 | } 109 | else 110 | { 111 | DbSet.Attach(entity); 112 | DbSet.Remove(entity); 113 | } 114 | } 115 | 116 | public void Delete(Expression> predicate, bool forceDelete = false) 117 | { 118 | T model = DbSet.FirstOrDefault(predicate); 119 | 120 | if (model != null) 121 | Delete(model, forceDelete); 122 | } 123 | public void BulkDelete(List entityList) 124 | { 125 | foreach (var entity in entityList) 126 | { 127 | DbSet.Remove(entity); 128 | } 129 | } 130 | 131 | public T Get(Expression> predicate) 132 | { 133 | IQueryable iQueryable = DbSet 134 | .Where(predicate); 135 | return iQueryable.ToList().FirstOrDefault(); 136 | } 137 | 138 | public TResult Get(Expression> predicate, Expression> @select) 139 | { 140 | IQueryable iQueryable = DbSet 141 | .Where(predicate); 142 | return iQueryable.Select(@select).FirstOrDefault(); 143 | } 144 | 145 | public T Get(Expression> predicate, List includePaths) 146 | { 147 | IQueryable iQueryable = DbSet 148 | .Where(predicate).Include(includePaths); 149 | return iQueryable.ToList().FirstOrDefault(); 150 | } 151 | 152 | public IQueryable GetAll() 153 | { 154 | IQueryable iQueryable = DbSet.Where(x => x != null); 155 | return iQueryable; 156 | } 157 | 158 | public IQueryable GetAll(System.Linq.Expressions.Expression> predicate) 159 | { 160 | IQueryable iQueryable = DbSet 161 | .Where(predicate); 162 | return iQueryable; 163 | } 164 | 165 | public IQueryable GetAll(System.Linq.Expressions.Expression> predicate, List includePaths) 166 | { 167 | IQueryable iQueryable = DbSet 168 | .Where(predicate).Include(includePaths); 169 | return iQueryable; 170 | } 171 | 172 | public IQueryable SelectList(Expression> where, Expression> select) 173 | { 174 | throw new NotImplementedException(); 175 | } 176 | 177 | public IQueryable SelectList(Expression> @where, Expression> @select) 178 | { 179 | IQueryable iQueryable = DbSet 180 | .Where(@where).Select(@select); 181 | return iQueryable; 182 | } 183 | 184 | public List SendSql(string sqlQuery) 185 | { 186 | throw new NotImplementedException(); 187 | } 188 | 189 | 190 | /// 191 | /// Verilen veriyi context üzerinde günceller. 192 | /// 193 | /// Güncellenecek entity 194 | public void Update(T entity) 195 | { 196 | DbSet.Attach(entity); 197 | DbContext.Entry(entity).State = EntityState.Modified; 198 | 199 | foreach (var propertyEntry in DbContext.Entry(entity).Properties) 200 | { 201 | foreach (var customAttribute in propertyEntry.Metadata.PropertyInfo.GetCustomAttributes()) 202 | { 203 | if (customAttribute.TypeId.Equals(typeof(DisableChangeTrackAttribute))) 204 | { 205 | propertyEntry.IsModified = false; 206 | } 207 | } 208 | } 209 | } 210 | 211 | public void UpdateProperties(T entity, params string[] changeProperties) 212 | { 213 | DbSet.Attach(entity); 214 | DbContext.Entry(entity).State = EntityState.Modified; 215 | 216 | foreach (var propertyEntry in DbContext.Entry(entity).Properties) 217 | { 218 | if (!changeProperties.Contains(propertyEntry.Metadata.PropertyInfo.Name)) 219 | propertyEntry.IsModified = false; 220 | 221 | foreach (var customAttribute in propertyEntry.Metadata.PropertyInfo.GetCustomAttributes()) 222 | { 223 | if (customAttribute.TypeId.Equals(typeof(DisableChangeTrackAttribute))) 224 | { 225 | propertyEntry.IsModified = false; 226 | } 227 | } 228 | } 229 | } 230 | 231 | public void Update(Expression> predicate, T entity) 232 | { 233 | throw new NotImplementedException(); 234 | } 235 | 236 | public int SendSqlScalar(string sqlQuery) 237 | { 238 | return DbContext.Database.ExecuteSqlRaw(sqlQuery); 239 | } 240 | } 241 | } 242 | -------------------------------------------------------------------------------- /DMicroservices/DataAccess/UnitOfWork/ICustomDbContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace DMicroservices.DataAccess.UnitOfWork 4 | { 5 | public interface ICustomDbContext 6 | { 7 | public string MYSQL_URI { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /DMicroservices/DataAccess/UnitOfWork/IUnitOfWork.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using DMicroservices.DataAccess.Repository; 3 | using Microsoft.EntityFrameworkCore; 4 | 5 | namespace DMicroservices.DataAccess.UnitOfWork 6 | { 7 | public interface IUnitOfWork : IDisposable 8 | { 9 | IRepository GetRepository() where T : class; 10 | IRepository GetReadonlyRepository() where T : class; 11 | int SaveChanges(); 12 | DbContext GetDbContext(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /DMicroservices/DataAccess/UnitOfWork/UnitOfWorkFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using DMicroservices.DataAccess.MongoRepository.Interfaces; 5 | using DMicroservices.DataAccess.MongoRepository.Settings; 6 | using Microsoft.EntityFrameworkCore; 7 | using MongoDB.Driver; 8 | 9 | namespace DMicroservices.DataAccess.UnitOfWork 10 | { 11 | public static class UnitOfWorkFactory 12 | { 13 | public static UnitOfWork CreateUnitOfWork() where T : DbContext, ICustomDbContext 14 | { 15 | return new UnitOfWork(); 16 | } 17 | public static UnitOfWork CreateUnitOfWork(object companyNo) where T : DbContext, ICustomDbContext 18 | { 19 | if (companyNo != null) 20 | return new UnitOfWork("CompanyNo", companyNo); 21 | return new UnitOfWork(); 22 | } 23 | 24 | public static UnitOfWork CreateUnitOfWork(string filterPropertyName, object filterPropertyValue) where T : DbContext, ICustomDbContext 25 | { 26 | return new UnitOfWork(filterPropertyName, filterPropertyValue); 27 | } 28 | 29 | public static UnitOfWork CreateUnitOfWork(UnitOfWorkSettings unitOfWorkSettings) where T : DbContext, ICustomDbContext 30 | { 31 | return new UnitOfWork(unitOfWorkSettings); 32 | } 33 | 34 | public static UnitOfWork CreateUnitOfWork(object companyNo, UnitOfWorkSettings unitOfWorkSettings) where T : DbContext, ICustomDbContext 35 | { 36 | if (companyNo != null) 37 | return new UnitOfWork("CompanyNo", companyNo, unitOfWorkSettings); 38 | return new UnitOfWork(unitOfWorkSettings); 39 | } 40 | 41 | public static UnitOfWork CreateUnitOfWork(Type unitOfWorkType) 42 | { 43 | return new UnitOfWork(unitOfWorkType); 44 | } 45 | 46 | public static UnitOfWork CreateUnitOfWork(object companyNo, Type unitOfWorkType) 47 | { 48 | if (companyNo != null) 49 | return new UnitOfWork("CompanyNo", companyNo, unitOfWorkType); 50 | return new UnitOfWork(unitOfWorkType); 51 | } 52 | 53 | public static UnitOfWork CreateUnitOfWork(string filterPropertyName, object filterPropertyValue, Type unitOfWorkType) 54 | { 55 | return new UnitOfWork(filterPropertyName, filterPropertyValue, unitOfWorkType); 56 | } 57 | 58 | public static UnitOfWork CreateUnitOfWork(UnitOfWorkSettings unitOfWorkSettings, Type unitOfWorkType) 59 | { 60 | return new UnitOfWork(unitOfWorkSettings, unitOfWorkType); 61 | } 62 | 63 | public static UnitOfWork CreateUnitOfWork(object companyNo, UnitOfWorkSettings unitOfWorkSettings, Type unitOfWorkType) 64 | { 65 | if (companyNo != null) 66 | return new UnitOfWork("CompanyNo", companyNo, unitOfWorkSettings, unitOfWorkType); 67 | return new UnitOfWork(unitOfWorkSettings, unitOfWorkType); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /DMicroservices/DataAccess/UnitOfWork/UnitOfWorkFactoryBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using DMicroservices.DataAccess.MongoRepository.Interfaces; 5 | using DMicroservices.DataAccess.MongoRepository.Settings; 6 | using Microsoft.EntityFrameworkCore; 7 | using MongoDB.Driver; 8 | 9 | namespace DMicroservices.DataAccess.UnitOfWork 10 | { 11 | public abstract class UnitOfWorkFactoryBase 12 | { 13 | public virtual UnitOfWork CreateUnitOfWork() where T : DbContext, ICustomDbContext 14 | { 15 | return new UnitOfWork(); 16 | } 17 | public virtual UnitOfWork CreateUnitOfWork(object companyNo) where T : DbContext, ICustomDbContext 18 | { 19 | if (companyNo != null) 20 | return new UnitOfWork("CompanyNo", companyNo); 21 | return new UnitOfWork(); 22 | } 23 | 24 | public virtual UnitOfWork CreateUnitOfWork(string filterPropertyName, object filterPropertyValue) where T : DbContext, ICustomDbContext 25 | { 26 | return new UnitOfWork(filterPropertyName, filterPropertyValue); 27 | } 28 | 29 | public virtual UnitOfWork CreateUnitOfWork(UnitOfWorkSettings unitOfWorkSettings) where T : DbContext, ICustomDbContext 30 | { 31 | return new UnitOfWork(unitOfWorkSettings); 32 | } 33 | 34 | public virtual UnitOfWork CreateUnitOfWork(object companyNo, UnitOfWorkSettings unitOfWorkSettings) where T : DbContext, ICustomDbContext 35 | { 36 | if (companyNo != null) 37 | return new UnitOfWork("CompanyNo", companyNo, unitOfWorkSettings); 38 | return new UnitOfWork(unitOfWorkSettings); 39 | } 40 | 41 | public virtual UnitOfWork CreateUnitOfWork(Type unitOfWorkType) 42 | { 43 | return new UnitOfWork(unitOfWorkType); 44 | } 45 | 46 | public virtual UnitOfWork CreateUnitOfWork(object companyNo, Type unitOfWorkType) 47 | { 48 | if (companyNo != null) 49 | return new UnitOfWork("CompanyNo", companyNo, unitOfWorkType); 50 | return new UnitOfWork(unitOfWorkType); 51 | } 52 | 53 | public virtual UnitOfWork CreateUnitOfWork(string filterPropertyName, object filterPropertyValue, Type unitOfWorkType) 54 | { 55 | return new UnitOfWork(filterPropertyName, filterPropertyValue, unitOfWorkType); 56 | } 57 | 58 | public virtual UnitOfWork CreateUnitOfWork(UnitOfWorkSettings unitOfWorkSettings, Type unitOfWorkType) 59 | { 60 | return new UnitOfWork(unitOfWorkSettings, unitOfWorkType); 61 | } 62 | 63 | public virtual UnitOfWork CreateUnitOfWork(object companyNo, UnitOfWorkSettings unitOfWorkSettings, Type unitOfWorkType) 64 | { 65 | if (companyNo != null) 66 | return new UnitOfWork("CompanyNo", companyNo, unitOfWorkSettings, unitOfWorkType); 67 | return new UnitOfWork(unitOfWorkSettings, unitOfWorkType); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /DMicroservices/DataAccess/UnitOfWork/UnitOfWorkSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using System.Threading.Tasks; 6 | 7 | namespace DMicroservices.DataAccess.UnitOfWork 8 | { 9 | public class UnitOfWorkSettings 10 | { 11 | public bool ChangeDataCapture { get; set; } 12 | 13 | public string ChangedUserPropertyName { get; set; } 14 | 15 | public string IdPropertyName { get; set; } 16 | 17 | public string ConnectionUri { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /DMicroservices/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:56276/", 7 | "sslPort": 44354 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "DMicroservices": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development" 23 | }, 24 | "applicationUrl": "https://localhost:5001;http://localhost:5000" 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /DMicroservices/RabbitMq/Base/ConsumerRegistry.cs: -------------------------------------------------------------------------------- 1 | using DMicroservices.RabbitMq.Consumer; 2 | using DMicroservices.RabbitMq.Model; 3 | using DMicroservices.Utils.Logger; 4 | using Newtonsoft.Json; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | 10 | namespace DMicroservices.RabbitMq.Base 11 | { 12 | public class ConsumerRegistry 13 | { 14 | private Dictionary Consumers { get; set; } 15 | private Dictionary ConsumerParallelismCount { get; set; } 16 | 17 | #region Singleton Section 18 | private static readonly Lazy _instance = new Lazy(() => new ConsumerRegistry()); 19 | 20 | private ConsumerRegistry() 21 | { 22 | Consumers = new Dictionary(); 23 | ConsumerParallelismCount = new Dictionary(); 24 | } 25 | 26 | public static ConsumerRegistry Instance => _instance.Value; 27 | #endregion 28 | 29 | 30 | public void RegisterWithList(List consumerList) 31 | { 32 | foreach (var consumer in consumerList.Where(x => !Consumers.Values.Select(y => y.GetConsumerKey()).Contains($"{x.FullName}"))) 33 | { 34 | Register(consumer); 35 | } 36 | } 37 | 38 | public void RegisterWithList(List consumerList) 39 | { 40 | foreach (var consumer in consumerList.Where(x => !Consumers.Values.Select(y => y.GetConsumerKey()).Contains($"{x.Type.FullName}"))) 41 | { 42 | Register(consumer.Type, consumer.ParallelismCount); 43 | } 44 | } 45 | 46 | public void UnRegisterWithList(List consumerList, params Type[] consumerIgnores) 47 | { 48 | foreach (var consumer in Consumers.Keys.Where(x => !consumerList.Select(y => $"{y.FullName}_0").Contains(x) && !consumerIgnores.Select(y => $"{y.FullName}_0").Contains(x))) 49 | { 50 | UnRegister(consumer); 51 | } 52 | } 53 | 54 | /// 55 | /// Verilen consumer listesinde OLMAYAN, daha önce register yapılmış consumerleri durdurur. 56 | /// 57 | /// 58 | /// 59 | public void UnRegisterWithList(List consumerList, params string[] consumerIgnores) 60 | { 61 | List nameList = new List(); 62 | foreach (var activeConsumer in consumerList) 63 | { 64 | for (int i = 0; i <= activeConsumer.ParallelismCount; i++) 65 | { 66 | nameList.Add($"{activeConsumer.Type.FullName}_{i}"); 67 | } 68 | } 69 | 70 | foreach (var consumer in Consumers.Keys.Where(x => !nameList.Contains(x) && !consumerIgnores.Contains(x))) 71 | { 72 | UnRegister(consumer); 73 | } 74 | } 75 | 76 | public void Register(Type consumer, int parallelismCount = 0) 77 | { 78 | if (consumer.GetInterfaces().Length == 0 || consumer.GetInterfaces().Any(x => x.GetInterface("IConsumer") != null)) 79 | throw new Exception("Consumer must be implement IConsumer."); 80 | 81 | ElasticLogger.Instance.Info($"Called to Register! {consumer.FullName}"); 82 | 83 | if (ConsumerParallelismCount.ContainsKey(consumer.FullName)) 84 | throw new Exception($"Called to Register has been already added {consumer.FullName}"); 85 | 86 | ConsumerParallelismCount.Add(consumer.FullName, parallelismCount); 87 | for (int i = 0; i <= parallelismCount; i++) 88 | { 89 | try 90 | { 91 | string consumerKey = $"{consumer.FullName}_{i}"; 92 | RegisterConsumer(consumerKey, consumer); 93 | } 94 | catch (Exception e) 95 | { 96 | ElasticLogger.Instance.Error(e, $"ConsumerRegistry throw an error : {e.Message}"); 97 | } 98 | } 99 | } 100 | 101 | private void RegisterConsumer(string consumerKey, Type consumer) 102 | { 103 | ElasticLogger.Instance.Info($"Register has been named! {consumerKey}"); 104 | 105 | if (Consumers.All(keyValue => keyValue.Key != consumerKey)) 106 | { 107 | var consumerObject = (IConsumer)Activator.CreateInstance(consumer); 108 | 109 | lock (Consumers) 110 | { 111 | ElasticLogger.Instance.Info("Consumer register new request with: " + consumerKey); 112 | Consumers.Add(consumerKey, consumerObject); 113 | } 114 | } 115 | 116 | Consumers[consumerKey].StartConsume(); 117 | } 118 | 119 | public void UnRegister(string consumerKey) 120 | { 121 | lock (Consumers) 122 | { 123 | if (Consumers.Keys.Any(p => p == consumerKey)) 124 | { 125 | var consumer = Consumers[consumerKey]; 126 | consumer.StopConsume(); 127 | ConsumerParallelismCount.Remove(consumer.GetConsumerKey()); 128 | Consumers.Remove(consumerKey); 129 | } 130 | } 131 | } 132 | 133 | public void UnRegister(Type consumer) 134 | { 135 | lock (Consumers) 136 | { 137 | Consumers[$"{consumer.FullName}_0"].StopConsume(); 138 | Consumers.Remove($"{consumer.FullName}_0"); 139 | ConsumerParallelismCount.Remove(consumer.FullName); 140 | } 141 | } 142 | 143 | public void ClearAllRegisters(params Type[] consumerIgnores) 144 | { 145 | lock (Consumers) 146 | { 147 | var consumerList = Consumers 148 | .Where(x => consumerIgnores.All(m => x.Value.GetConsumerKey() != null && !x.Value.GetConsumerKey().Equals(m.FullName))).ToList(); 149 | 150 | List stopConsumeTaskList = new List(); 151 | foreach (var consumerItem in consumerList) 152 | { 153 | stopConsumeTaskList.Add(consumerItem.Value.StopConsume()); 154 | } 155 | 156 | Task.WaitAll(stopConsumeTaskList.ToArray()); 157 | } 158 | } 159 | 160 | public void ClearAllRegisters(params string[] consumerIgnores) 161 | { 162 | lock (Consumers) 163 | { 164 | var consumerList = Consumers.Where(x => consumerIgnores.All(m => x.Key != null && !x.Key.Equals(m))).ToList(); 165 | 166 | List stopConsumeTaskList = new List(); 167 | foreach (var consumerItem in consumerList) 168 | { 169 | stopConsumeTaskList.Add(consumerItem.Value.StopConsume()); 170 | } 171 | 172 | Task.WaitAll(stopConsumeTaskList.ToArray()); 173 | } 174 | } 175 | 176 | public void IncreaseParallelism(Type consumer) 177 | { 178 | int parallelismCount = ConsumerParallelismCount[consumer.FullName]++; 179 | string consumerKey = $"{consumer.FullName}_{parallelismCount + 1}"; 180 | RegisterConsumer(consumerKey, consumer); 181 | } 182 | 183 | public void DecreaseParallelism(Type consumer) 184 | { 185 | int parallelismCount = ConsumerParallelismCount[consumer.FullName]; 186 | if (parallelismCount == 0) 187 | { 188 | UnRegister(consumer); 189 | } 190 | else 191 | { 192 | string consumerKey = $"{consumer.FullName}_{parallelismCount}"; 193 | UnRegister(consumerKey); 194 | } 195 | 196 | ConsumerParallelismCount[consumer.FullName]--; 197 | } 198 | 199 | public Dictionary GetParallelismCount() 200 | { 201 | return ConsumerParallelismCount; 202 | } 203 | 204 | public void ChangePrefetch(Type consumerType, ushort prefetchCount) 205 | { 206 | foreach (var (consumerKey, consumer) in Consumers) 207 | { 208 | if (consumer.GetType().FullName.Equals(consumerType.FullName)) 209 | { 210 | consumer.ChangePrefetchCount(prefetchCount); 211 | } 212 | } 213 | } 214 | } 215 | 216 | public static class ConsumerExtensions 217 | { 218 | public static string GetConsumerKey(this IConsumer consumer) 219 | { 220 | return consumer.GetType().FullName; 221 | } 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /DMicroservices/RabbitMq/Base/ListenQueueAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace DMicroservices.RabbitMq.Base 4 | { 5 | 6 | public class ListenQueueAttribute : Attribute 7 | { 8 | public string ListenQueue { get; set; } 9 | public ListenQueueAttribute(string listenQueue) 10 | { 11 | ListenQueue = listenQueue; 12 | } 13 | 14 | /// 15 | /// add HOSTNAME after queuename 16 | /// 17 | /// 18 | /// 19 | public ListenQueueAttribute(string listenQueue, bool addHostnameEnvironment) 20 | { 21 | if (addHostnameEnvironment) 22 | { 23 | ListenQueue = listenQueue + Environment.GetEnvironmentVariable("HOSTNAME"); 24 | } 25 | else 26 | { 27 | ListenQueue = listenQueue; 28 | } 29 | } 30 | 31 | /// 32 | /// get from static property. 33 | /// 34 | /// 35 | /// 36 | public ListenQueueAttribute(Type type, string propertyName) 37 | { 38 | 39 | foreach (var property in type.GetProperties()) 40 | { 41 | if (property.Name.Equals(propertyName)) 42 | { 43 | ListenQueue = property.GetValue(null)?.ToString(); 44 | break; 45 | } 46 | } 47 | 48 | if (string.IsNullOrEmpty(ListenQueue)) 49 | { 50 | throw new Exception($"{propertyName} not found in type : {type.FullName}"); 51 | } 52 | 53 | 54 | 55 | 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /DMicroservices/RabbitMq/Base/RabbitMQConnection.cs: -------------------------------------------------------------------------------- 1 | using DMicroservices.RabbitMq.Model; 2 | using DMicroservices.Utils.Logger; 3 | using RabbitMQ.Client; 4 | using System; 5 | using System.Collections.Concurrent; 6 | using System.Collections.Generic; 7 | using DMicroservices.Utils.Exceptions; 8 | 9 | namespace DMicroservices.RabbitMq.Base 10 | { 11 | /// 12 | /// Rabbitmq bağlantı backend classı 13 | /// 14 | public class RabbitMqConnection 15 | { 16 | #region Singleton Section 17 | private static readonly Lazy _instance = new Lazy(() => new RabbitMqConnection()); 18 | 19 | 20 | public static RabbitMqConnection Instance => _instance.Value; 21 | #endregion 22 | 23 | #region Constructor 24 | 25 | /// 26 | /// Constructor 27 | /// 28 | public RabbitMqConnection() 29 | { 30 | } 31 | 32 | #endregion 33 | 34 | #region Properties 35 | 36 | private static readonly object _lockObj = new object(); 37 | 38 | public IConnection Connection { get; set; } 39 | 40 | private ConcurrentDictionary ConnectionList { get; set; } = new ConcurrentDictionary(); 41 | 42 | public bool IsConnected => Connection is { IsOpen: true }; 43 | 44 | #endregion 45 | 46 | #region Method 47 | 48 | /// 49 | /// Rabbitmq bağlantısı oluşturup döner 50 | /// 51 | /// 52 | public IConnection GetConnection() 53 | { 54 | if (IsConnected) 55 | return Connection; 56 | try 57 | { 58 | lock (_lockObj) 59 | { 60 | string hostName = Environment.GetEnvironmentVariable("HOSTNAME"); 61 | if (string.IsNullOrEmpty(hostName)) 62 | { 63 | hostName = Environment.GetEnvironmentVariable("COMPUTERNAME"); 64 | } 65 | if (IsConnected) 66 | return Connection; 67 | ConnectionFactory connectionFactory = new ConnectionFactory 68 | { 69 | Uri = new Uri(Environment.GetEnvironmentVariable("RABBITMQ_URI")), 70 | AutomaticRecoveryEnabled = false, 71 | ClientProvidedName = hostName 72 | }; 73 | Connection = connectionFactory.CreateConnection(); 74 | Connection.ConnectionShutdown += (sender, args) => 75 | { 76 | if (args.ReplyCode != 200) 77 | { 78 | ElasticLogger.Instance.ErrorSpecificIndexFormat(new Exception($"{args}"), "RabbitMQ/ConnectionShutdown", ConstantString.RABBITMQ_INDEX_FORMAT); 79 | } 80 | }; 81 | return Connection; 82 | } 83 | } 84 | catch (Exception ex) 85 | { 86 | Console.WriteLine(ex.Message); 87 | ElasticLogger.Instance.ErrorSpecificIndexFormat(ex, "RabbitmqConnection", ConstantString.RABBITMQ_INDEX_FORMAT); 88 | throw; 89 | } 90 | } 91 | 92 | public IConnection GetConnection(ConnectionType connectionType) 93 | { 94 | if (ConnectionList.TryGetValue(connectionType, out IConnection connectionObject) && connectionObject.IsOpen) 95 | return connectionObject; 96 | try 97 | { 98 | lock (_lockObj) 99 | { 100 | string hostName = Environment.GetEnvironmentVariable("HOSTNAME"); 101 | if (string.IsNullOrEmpty(hostName)) 102 | { 103 | hostName = Environment.GetEnvironmentVariable("COMPUTERNAME"); 104 | } 105 | if (ConnectionList.TryGetValue(connectionType, out IConnection connectionObjectInner) && connectionObjectInner.IsOpen) 106 | return connectionObjectInner; 107 | 108 | ConnectionFactory connectionFactory = new ConnectionFactory 109 | { 110 | Uri = new Uri(Environment.GetEnvironmentVariable("RABBITMQ_URI")), 111 | AutomaticRecoveryEnabled = false, 112 | ClientProvidedName = hostName 113 | }; 114 | var connection = connectionFactory.CreateConnection(); 115 | 116 | ConnectionList.TryAdd(connectionType, connection); 117 | connection.ConnectionShutdown += (sender, args) => 118 | { 119 | if (args.ReplyCode != 200) 120 | { 121 | ElasticLogger.Instance.ErrorSpecificIndexFormat(new Exception($"{args}"), "RabbitMQ/ConnectionShutdown", ConstantString.RABBITMQ_INDEX_FORMAT); 122 | } 123 | }; 124 | return connection; 125 | } 126 | } 127 | catch (Exception ex) 128 | { 129 | Console.WriteLine(ex.Message); 130 | ElasticLogger.Instance.ErrorSpecificIndexFormat(ex, "RabbitmqConnection", ConstantString.RABBITMQ_INDEX_FORMAT); 131 | return null; 132 | } 133 | } 134 | 135 | /// 136 | /// Channel oluşturup döner 137 | /// 138 | /// 139 | public IModel GetChannel(string queueName, bool durable = true, bool autoDelete = false) 140 | { 141 | IModel channel; 142 | IConnection connection = GetConnection(); 143 | try 144 | { 145 | channel = connection.CreateModel(); 146 | channel.QueueDeclarePassive(queueName); 147 | } 148 | catch 149 | { 150 | channel = connection.CreateModel(); 151 | channel.QueueDeclare(queueName, durable, false, autoDelete, null); 152 | } 153 | 154 | return channel; 155 | } 156 | 157 | /// 158 | /// Channel oluşturup döner 159 | /// 160 | /// 161 | public IModel GetChannel(string queueName, byte maxPriority, bool durable = true, bool autoDelete = false) 162 | { 163 | IModel channel; 164 | 165 | IConnection connection = GetConnection(); 166 | 167 | try 168 | { 169 | channel = connection.CreateModel(); 170 | channel.QueueDeclarePassive(queueName); 171 | } 172 | catch 173 | { 174 | channel = connection.CreateModel(); 175 | channel.QueueDeclare(queueName, durable, false, autoDelete, new Dictionary() 176 | { 177 | {"x-max-priority", maxPriority} 178 | }); 179 | } 180 | 181 | return channel; 182 | } 183 | /// 184 | /// Exchange Channel oluşturup döner 185 | /// 186 | /// 187 | public IModel GetExchangeChannel(ExchangeContent exchangeContent, string queueName, bool durable, bool autoDelete = false) 188 | { 189 | IConnection connection = GetConnection(); 190 | IModel channel = connection.CreateModel(); 191 | channel.ExchangeDeclare(exchangeContent.ExchangeName, exchangeContent.ExchangeType); 192 | channel.QueueDeclare(queueName, durable, false, autoDelete); 193 | channel.QueueBind(queueName, exchangeContent.ExchangeName, exchangeContent.RoutingKey, exchangeContent.Headers); 194 | return channel; 195 | } 196 | 197 | #endregion 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /DMicroservices/RabbitMq/Base/RabbitMqHealthCheck.cs: -------------------------------------------------------------------------------- 1 | using DMicroservices.DataAccess.Redis; 2 | using DMicroservices.Utils.Logger; 3 | using Microsoft.Extensions.Diagnostics.HealthChecks; 4 | using System; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | 8 | namespace DMicroservices.RabbitMq.Base 9 | { 10 | public class RabbitMqHealthCheck : IHealthCheck 11 | { 12 | private Action _afterConnectionAction; 13 | public RabbitMqHealthCheck(Action afterConnectionAction) 14 | { 15 | _afterConnectionAction = afterConnectionAction; 16 | } 17 | public RabbitMqHealthCheck() 18 | { 19 | } 20 | public Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) 21 | { 22 | if (!RabbitMqConnection.Instance.IsConnected) 23 | { 24 | RabbitMQ.Client.IConnection rabbitConnection = null; 25 | var tryConnectionTask = new Task(() => 26 | { 27 | try 28 | { 29 | rabbitConnection = RabbitMqConnection.Instance.GetConnection(); 30 | } 31 | catch 32 | { 33 | //ignored 34 | } 35 | }); 36 | tryConnectionTask.Start(); 37 | tryConnectionTask.Wait(TimeSpan.FromSeconds(1)); 38 | if (rabbitConnection == null || !rabbitConnection.IsOpen) 39 | { 40 | ElasticLogger.Instance.Info($"RabbitMQ Connection Lost"); 41 | return Task.FromResult(HealthCheckResult.Unhealthy("RabbitMQ Connection Lost")); 42 | } 43 | else 44 | { 45 | if (_afterConnectionAction != null) 46 | _afterConnectionAction.Invoke("Called /IsReady Method"); 47 | } 48 | } 49 | 50 | return Task.FromResult(HealthCheckResult.Healthy()); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /DMicroservices/RabbitMq/ConstantString.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace DMicroservices.RabbitMq 7 | { 8 | public static class ConstantString 9 | { 10 | public const string RABBITMQ_INDEX_FORMAT = "rabbit-serilog-{0:yyyy.MM.dd}"; 11 | public const string REDIS_LOG_INDEX_FORMAT = "redis-serilog-{0:yyyy.MM.dd}"; 12 | public const string RABBIT_ACKED_KEY = "RABBIT_ACKED"; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /DMicroservices/RabbitMq/Consumer/BasicRawConsumer.cs: -------------------------------------------------------------------------------- 1 | using DMicroservices.RabbitMq.Base; 2 | using DMicroservices.RabbitMq.Model; 3 | using DMicroservices.Utils.Logger; 4 | using RabbitMQ.Client; 5 | using RabbitMQ.Client.Events; 6 | using RabbitMQ.Client.Exceptions; 7 | using System; 8 | using System.Diagnostics; 9 | using System.Reflection; 10 | using System.Text; 11 | using System.Threading; 12 | using System.Threading.Tasks; 13 | 14 | namespace DMicroservices.RabbitMq.Consumer 15 | { 16 | /// 17 | /// Consuming base 18 | /// 19 | /// 20 | public abstract class BasicRawConsumer : IConsumer 21 | { 22 | private string _listenQueueName; 23 | 24 | public abstract bool AutoAck { get; } 25 | 26 | public virtual ushort PrefectCount { get; set; } 27 | 28 | public virtual byte MaxPriority { get; set; } = 0; 29 | public virtual bool Durable { get; set; } = true; 30 | public virtual bool AutoDelete { get; set; } = false; 31 | 32 | public virtual ExchangeContent ExchangeContent { get; set; } 33 | 34 | public virtual Action DataReceivedAction { get; } 35 | 36 | private bool _consumerListening = false; 37 | 38 | public bool ConsumerListening 39 | { 40 | get => _consumerListening; 41 | set 42 | { 43 | _consumerListening = value; 44 | } 45 | } 46 | 47 | /// 48 | /// Modeli dinlemek için kullanıclan event 49 | /// 50 | private EventingBasicConsumer _eventingBasicConsumer; 51 | 52 | /// 53 | /// bu consumer tekrar initialize edilebilir mi? 54 | /// 55 | private bool _dontReinitialize = false; 56 | 57 | private IModel _rabbitMqChannel; 58 | 59 | private readonly object _stateChangeLockObject = new object(); 60 | 61 | 62 | protected BasicRawConsumer() 63 | { 64 | var listenQueueAttribute = GetType().GetCustomAttribute(); 65 | if (listenQueueAttribute == null || string.IsNullOrEmpty(listenQueueAttribute.ListenQueue)) 66 | { 67 | throw new Exception($"{GetType().FullName} sınıfı için ListenQueue attibute zorunludur"); 68 | } 69 | 70 | _listenQueueName = listenQueueAttribute.ListenQueue; 71 | } 72 | 73 | 74 | private void RabbitMqChannelShutdown() 75 | { 76 | try 77 | { 78 | _eventingBasicConsumer.OnCancel(_eventingBasicConsumer.ConsumerTags); 79 | _rabbitMqChannel?.Dispose(); 80 | _rabbitMqChannel = null; 81 | } 82 | catch 83 | { 84 | //ignored 85 | } 86 | 87 | Thread.Sleep(3000); 88 | 89 | ConsumerListening = false; 90 | if (_dontReinitialize) 91 | return; 92 | 93 | StartConsume(); 94 | 95 | } 96 | 97 | private void DocumentConsumerOnReceived(object sender, BasicDeliverEventArgs e) 98 | { 99 | var rawData = Encoding.UTF8.GetString(e.Body.ToArray()); 100 | try 101 | { 102 | DataReceivedAction(rawData, e); 103 | } 104 | catch (Exception ex) 105 | { 106 | ElasticLogger.Instance.ErrorSpecificIndexFormat(ex, $"DocumentConsumer generic data received exception: {ex.Message}", 107 | ConstantString.RABBITMQ_INDEX_FORMAT, new System.Collections.Generic.Dictionary() { { "Data:", rawData } }); 108 | _rabbitMqChannel.BasicNack(e.DeliveryTag, false, false); 109 | } 110 | } 111 | 112 | protected void BasicAck(ulong deliveryTag, bool multiple) 113 | { 114 | _rabbitMqChannel.BasicAck(deliveryTag, multiple); 115 | } 116 | 117 | protected EventingBasicConsumer GetCurrentConsumer() 118 | { 119 | return _eventingBasicConsumer; 120 | } 121 | 122 | public Task StartConsume() 123 | { 124 | return Task.Run(() => 125 | { 126 | Debug.WriteLine($"Consumer {_listenQueueName} start requested. Status: New"); 127 | lock (_stateChangeLockObject) 128 | { 129 | Debug.WriteLine($"Consumer {_listenQueueName} start process started. Status: Pending"); 130 | if (ConsumerListening) 131 | { 132 | Debug.WriteLine($"Consumer {_listenQueueName} start process started. Status: Already Listening"); 133 | return; 134 | } 135 | 136 | try 137 | { 138 | if (string.IsNullOrEmpty(_listenQueueName)) 139 | { 140 | ElasticLogger.Instance.InfoSpecificIndexFormat("Consumer QueueName was null", ConstantString.RABBITMQ_INDEX_FORMAT); 141 | } 142 | 143 | if (ExchangeContent != null) 144 | { 145 | if (ExchangeContent.RoutingKey == null || 146 | string.IsNullOrEmpty(ExchangeContent.ExchangeName) || 147 | string.IsNullOrEmpty(ExchangeContent.ExchangeType)) 148 | throw new Exception("ExchangeContent contains null object(s)!"); 149 | _rabbitMqChannel = 150 | RabbitMqConnection.Instance.GetExchangeChannel(ExchangeContent, _listenQueueName, Durable, AutoDelete); 151 | } 152 | else 153 | { 154 | _rabbitMqChannel = MaxPriority > 0 155 | ? RabbitMqConnection.Instance.GetChannel(_listenQueueName, MaxPriority, Durable, AutoDelete) 156 | : RabbitMqConnection.Instance.GetChannel(_listenQueueName, Durable, AutoDelete); 157 | } 158 | 159 | if (PrefectCount != 0) 160 | _rabbitMqChannel.BasicQos(0, PrefectCount, false); 161 | 162 | _eventingBasicConsumer = new EventingBasicConsumer(_rabbitMqChannel); 163 | _eventingBasicConsumer.ConsumerCancelled += (sender, args) => 164 | { 165 | ElasticLogger.Instance.ErrorSpecificIndexFormat( 166 | new Exception($"{args} Queue: {_listenQueueName}"), "RabbitMQ/ModelShutdown", 167 | ConstantString.RABBITMQ_INDEX_FORMAT); 168 | Task.Run(RabbitMqChannelShutdown); 169 | }; 170 | _eventingBasicConsumer.Received += DocumentConsumerOnReceived; 171 | _rabbitMqChannel.BasicConsume(_listenQueueName, AutoAck, _eventingBasicConsumer); 172 | ConsumerListening = true; 173 | _rabbitMqChannel.ModelShutdown += (sender, args) => 174 | { 175 | if (args.ReplyCode != 200) 176 | { 177 | ElasticLogger.Instance.ErrorSpecificIndexFormat(new Exception($"{args} Queue: {_listenQueueName}"), "RabbitMQ/ModelShutdown", ConstantString.RABBITMQ_INDEX_FORMAT); 178 | Task.Run(RabbitMqChannelShutdown); 179 | } 180 | }; 181 | } 182 | catch (RabbitMQClientException connectionException) 183 | { 184 | if (!ConsumerListening) 185 | { 186 | Task.Run(RabbitMqChannelShutdown); 187 | } 188 | ElasticLogger.Instance.ErrorSpecificIndexFormat(connectionException, $"RabbitMQ Connection Exception! Queue: {_listenQueueName}", ConstantString.RABBITMQ_INDEX_FORMAT); 189 | } 190 | catch (Exception ex) 191 | { 192 | //try connect if not connected. 193 | if (!ConsumerListening) 194 | { 195 | Task.Run(RabbitMqChannelShutdown); 196 | } 197 | ElasticLogger.Instance.ErrorSpecificIndexFormat(ex, $"RabbitMQ/RabbitmqConsumer Error! Queue: {_listenQueueName}", ConstantString.RABBITMQ_INDEX_FORMAT); 198 | } 199 | } 200 | Debug.WriteLine($"Consumer {_listenQueueName} start completed. Status: Success"); 201 | }); 202 | } 203 | 204 | public Task StopConsume() 205 | { 206 | return Task.Run(() => 207 | { 208 | Debug.WriteLine($"Consumer {_listenQueueName} stop requested."); 209 | lock (_stateChangeLockObject) 210 | { 211 | Debug.WriteLine($"Consumer {_listenQueueName} stop process started."); 212 | if (!ConsumerListening) 213 | return; 214 | 215 | _dontReinitialize = true; 216 | 217 | _eventingBasicConsumer.Received -= DocumentConsumerOnReceived; 218 | Thread.Sleep(TimeSpan.FromSeconds(15)); 219 | _eventingBasicConsumer.OnCancel(_eventingBasicConsumer.ConsumerTags); 220 | _rabbitMqChannel?.Dispose(); 221 | _rabbitMqChannel = null; 222 | ConsumerListening = false; 223 | Debug.WriteLine($"Consumer {_listenQueueName} stop completed."); 224 | } 225 | }); 226 | } 227 | 228 | public void ChangePrefetchCount(ushort prefetchCount) 229 | { 230 | PrefectCount = prefetchCount; 231 | if (_rabbitMqChannel.IsOpen) 232 | { 233 | _rabbitMqChannel.BasicQos(0, prefetchCount, false); 234 | } 235 | } 236 | 237 | public string GetListenQueueName() 238 | { 239 | return _listenQueueName; 240 | } 241 | } 242 | } 243 | -------------------------------------------------------------------------------- /DMicroservices/RabbitMq/Consumer/IBasicConsumer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace DMicroservices.RabbitMq.Consumer 5 | { 6 | public interface IConsumer 7 | { 8 | 9 | bool AutoAck { get; } 10 | 11 | ushort PrefectCount { get; set; } 12 | 13 | Task StartConsume(); 14 | 15 | Task StopConsume(); 16 | 17 | void ChangePrefetchCount(ushort prefetchCount); 18 | string GetListenQueueName(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /DMicroservices/RabbitMq/Model/ConnectionType.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace DMicroservices.RabbitMq.Model 4 | { 5 | public enum ConnectionType 6 | { 7 | PUBLISH, 8 | CONSUMER 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /DMicroservices/RabbitMq/Model/ConsumerActiveModel.cs: -------------------------------------------------------------------------------- 1 | using DMicroservices.RabbitMq.Consumer; 2 | using System; 3 | 4 | namespace DMicroservices.RabbitMq.Model 5 | { 6 | public class ConsumerActiveModel 7 | { 8 | public Type Type { get; set; } 9 | 10 | public IConsumer IConsumer { get; set; } 11 | 12 | public ushort ParallelismCount { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /DMicroservices/RabbitMq/Model/ExchangeContent.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace DMicroservices.RabbitMq.Model 4 | { 5 | public class ExchangeContent 6 | { 7 | public string ExchangeName { get; set; } 8 | 9 | // örn: ExchangeType.Fanout 10 | public string ExchangeType { get; set; } 11 | 12 | public string RoutingKey { get; set; } = string.Empty; 13 | 14 | public Dictionary Headers { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /DMicroservices/Utils/Exceptions/RabbitMqConnectionException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace DMicroservices.Utils.Exceptions 4 | { 5 | public class RabbitMqConnectionException : Exception 6 | { 7 | 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /DMicroservices/Utils/Extensions/ConnectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace DMicroservices.Utils.Extensions 4 | { 5 | public static class ConnectionExtensions 6 | { 7 | public static string GetConnectionString() 8 | { 9 | return string.Format("server={0};port={1};user={2};password={3};database={4}", 10 | Environment.GetEnvironmentVariable("MYSQL_IP") 11 | , Environment.GetEnvironmentVariable("MYSQL_PORT") 12 | , Environment.GetEnvironmentVariable("MYSQL_USER") 13 | , Environment.GetEnvironmentVariable("MYSQL_PASWORD") 14 | , Environment.GetEnvironmentVariable("MYSQL_DB")); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /DMicroservices/Utils/Extensions/CryptoExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security.Cryptography; 3 | using System.Text; 4 | 5 | namespace DMicroservices.Utils.Extensions 6 | { 7 | public class CryptoExtensions 8 | { 9 | /// 10 | /// Verilen değerin MD5 özetini alır. 11 | /// 12 | /// 13 | /// 14 | public static string Md5Encrypt(string value) 15 | { 16 | if (!string.IsNullOrEmpty(value)) 17 | { 18 | string val = string.Empty; 19 | MD5CryptoServiceProvider md5Cyripto = new MD5CryptoServiceProvider(); 20 | byte[] bytes = Encoding.ASCII.GetBytes(value); 21 | byte[] arrays = md5Cyripto.ComputeHash(bytes); 22 | int capacity = (int)Math.Round(arrays.Length * 3 + (double)arrays.Length / 8); 23 | StringBuilder builder = new StringBuilder(capacity); 24 | int num = arrays.Length - 1; 25 | for (int i = 0; i <= num; i++) 26 | { 27 | builder.Append(BitConverter.ToString(arrays, i, 1)); 28 | } 29 | val = builder.ToString().TrimEnd(new char[] { ' ' }); 30 | return val; 31 | } 32 | return null; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /DMicroservices/Utils/Extensions/DatabaseExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore.Metadata; 6 | 7 | namespace DMicroservices.Utils.Extensions 8 | { 9 | /// 10 | /// https://stackoverflow.com/a/49597502 11 | /// 12 | public static partial class DatabaseExtensions 13 | { 14 | public static IQueryable Include(this IQueryable source, IEnumerable navigationPropertyPaths) 15 | where T : class 16 | { 17 | return navigationPropertyPaths.Aggregate(source, (query, path) => query.Include(path)); 18 | } 19 | 20 | public static IEnumerable GetIncludePaths(this DbContext context, Type clrEntityType) 21 | { 22 | var entityType = context.Model.FindEntityType(clrEntityType); 23 | var includedNavigation = new HashSet(); 24 | var stack = new Stack>(); 25 | while (true) 26 | { 27 | var entityNavigation = new List(); 28 | foreach (var navigation in entityType.GetNavigations()) 29 | { 30 | if (includedNavigation.Add(navigation)) 31 | entityNavigation.Add(navigation); 32 | } 33 | if (entityNavigation.Count == 0) 34 | { 35 | if (stack.Count > 0) 36 | yield return string.Join(".", stack.Reverse().Select(e => e.Current.Name)); 37 | } 38 | else 39 | { 40 | foreach (var navigation in entityNavigation) 41 | { 42 | var inverseNavigation = navigation.FindInverse(); 43 | if (inverseNavigation != null) 44 | includedNavigation.Add(inverseNavigation); 45 | } 46 | stack.Push(entityNavigation.GetEnumerator()); 47 | } 48 | while (stack.Count > 0 && !stack.Peek().MoveNext()) 49 | stack.Pop(); 50 | if (stack.Count == 0) break; 51 | entityType = stack.Peek().Current.GetTargetType(); 52 | } 53 | } 54 | 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /DMicroservices/Utils/Extensions/ExpressionExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | 5 | namespace DMicroservices.Utils.Extensions 6 | { 7 | public static class ExpressionExtensions 8 | { 9 | /// 10 | /// Given the key column name in item type. 11 | /// 12 | /// Requested key name in this item 13 | /// 14 | public static string GetIdentifierColumnName(this Type item) 15 | { 16 | foreach (var propertyInfo in item.GetProperties()) 17 | { 18 | foreach (var propertyInfoCustomAttribute in propertyInfo.CustomAttributes) 19 | { 20 | if (propertyInfoCustomAttribute.AttributeType.Name.Equals("KeyAttribute")) 21 | return propertyInfo.Name; 22 | } 23 | } 24 | 25 | throw new KeyNotFoundException("The object was not contains key property."); 26 | } 27 | 28 | /// 29 | /// Given the created expression by identifier column. 30 | /// 31 | /// 32 | public static Expression> GetIdentifierExpression(this long id) 33 | { 34 | ParameterExpression argParams = Expression.Parameter(typeof(T), "x"); 35 | Expression filterProp = Expression.Property(argParams, typeof(T).GetIdentifierColumnName()); 36 | ConstantExpression filterValue = Expression.Constant(id); 37 | return Expression.Lambda>(Expression.Equal(filterProp, filterValue), argParams); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /DMicroservices/Utils/Extensions/OverloadedMethodFinder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | 5 | namespace DMicroservices.Utils.Extensions 6 | { 7 | /// 8 | /// Helps find an overloaded method 9 | /// https://stackoverflow.com/questions/17634908/enumerable-contains-with-methodinfo 10 | /// 11 | public static class OverloadedMethodFinder 12 | { 13 | 14 | #region Public Static Methods 15 | 16 | /// 17 | /// Attempts to find the overloaded method that we want to call. Returns null if not found. This overload looks at the parameter types passed in vs method parameters off of the type we pass in 18 | /// 19 | /// What is the method to name to find 20 | /// The type to retrieve the methods off of, so we can look through it and try to find the correct method 21 | /// Look for the method parameter types in the method to match. If the method takes a string and an int, then we will look for that in every method 22 | /// Method info found, or null value if not found 23 | public static MethodInfo FindOverloadedMethodToCall(string MethodNameToRetrieve, Type TypeToLookThroughTheMethods, params Type[] MethodParameterTypes) 24 | { 25 | //going to use the overload. So we can create the func with calling the other method 26 | return FindOverloadedMethodToCall(MethodNameToRetrieve, TypeToLookThroughTheMethods, x => MethodParameterSelector(x, MethodParameterTypes)); 27 | } 28 | 29 | /// 30 | /// Attempts to find the overloaded method that we want to call. Returns null if not found. This method will try to evaluate the MethodSelect for each method and check to see if it returns true. 31 | /// 32 | /// What is the method to name to find 33 | /// Gives the calling method the ability to look through the parameters and pick the correct method 34 | /// The type to retrieve the methods off of, so we can look through it and try to find the correct method 35 | /// Method info found, or null value if not found 36 | public static MethodInfo FindOverloadedMethodToCall(string MethodNameToRetrieve, Type TypeToLookThroughTheMethods, Func MethodSelector) 37 | { 38 | //use the overload 39 | return FindOverloadedMethodToCall(MethodNameToRetrieve, TypeToLookThroughTheMethods.GetMethods(), MethodSelector); 40 | } 41 | 42 | /// 43 | /// Attempts to find the overloaded method that we want to call. Returns null if not found. This method will try to evaluate the MethodSelect for each method and check to see if it returns true. 44 | /// Call this method if you already have the method info's that match the same name you are looking for 45 | /// 46 | /// What is the method to name to find 47 | /// Gives the calling method the ability to look through the parameters and pick the correct method 48 | /// Methods that have the same name. Or methods to loop through and inspect against the method selector. 49 | /// Method info found, or null value if not found 50 | public static MethodInfo FindOverloadedMethodToCall(string MethodNameToRetrieve, IEnumerable MethodsToLookThrough, Func MethodSelector) 51 | { 52 | //let's start looping through the methods to see if we can find a match 53 | foreach (MethodInfo MethodToInspect in MethodsToLookThrough) 54 | { 55 | //is it the method name? and does it match the method selector passed in? 56 | if (string.Equals(MethodNameToRetrieve, MethodToInspect.Name, StringComparison.OrdinalIgnoreCase) && MethodSelector(MethodToInspect)) 57 | { 58 | //we have a match...return the method now 59 | return MethodToInspect; 60 | } 61 | } 62 | 63 | //we never found a match, so just return null 64 | return null; 65 | } 66 | 67 | #endregion 68 | 69 | #region Private Static Methods 70 | 71 | /// 72 | /// Private helper method to look at the current method and inspect it for the method parameter types. If they match return true, else return false 73 | /// 74 | /// Method to evaluate and check if we have a match based on the method parameter types 75 | /// 76 | /// Do we have a match? Do the method parameter types match? 77 | private static bool MethodParameterSelector(MethodInfo MethodToEvaluate, params Type[] MethodParameterTypes) 78 | { 79 | //we are going to match the GetParameters and the MethodParameterTypes. It needs to match index for index and type for type. So GetParameters[0].Type must match MethodParameterTypes[0].Type...[1].Type must match [1].Type 80 | 81 | //holds the index with the method parameter types we are up too 82 | int i = 0; 83 | 84 | //let's loop through the parameters 85 | foreach (ParameterInfo thisParameter in MethodToEvaluate.GetParameters()) 86 | { 87 | //it's a generic parameter...ie...TSource then we are going to ignore it because whatever we pass in would be TSource 88 | if (!thisParameter.ParameterType.IsGenericParameter) 89 | { 90 | //is this a generic type? we need to compare this differently 91 | if (thisParameter.ParameterType.IsGenericType) 92 | { 93 | //is the method parameter a generic type? 94 | if (!MethodParameterTypes[i].IsGenericType) 95 | { 96 | //it isn't so return false..cause they aren't the same 97 | return false; 98 | } 99 | 100 | //if the generic type's don't match then return false...This might be problematic...it works for the scenario which I'm using it for so we will leave this and modify afterwards 101 | if (thisParameter.ParameterType.GetGenericTypeDefinition() != MethodParameterTypes[i].GetGenericTypeDefinition()) 102 | { 103 | //doesn't match return false 104 | return false; 105 | } 106 | } 107 | else if (thisParameter.ParameterType != MethodParameterTypes[i].UnderlyingSystemType) 108 | { 109 | //this is a regular parameter so we can compare it normally 110 | //we don't have a match...so return false 111 | return false; 112 | } 113 | } 114 | 115 | //increment the index 116 | i++; 117 | } 118 | 119 | //if we get here then everything matches so return true 120 | return true; 121 | } 122 | 123 | #endregion 124 | 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /DMicroservices/Utils/ObjectMapper/ObjectMapper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Reflection; 6 | 7 | namespace DMicroservices.Utils.ObjectMapper 8 | { 9 | public class ObjectMapper 10 | { 11 | /// 12 | /// Verilen kaynak nesneyi hedef nesnenin özelliklerine set eder. 13 | /// 14 | /// Hedef 15 | /// Kaynak 16 | public static void Map(object target, object source) 17 | { 18 | if (source != null && target != null) 19 | { 20 | PropertyInfo[] targetProperties = target.GetType().GetProperties(); 21 | foreach (var sourceProperty in source.GetType().GetProperties()) 22 | { 23 | PropertyInfo targetProperty = targetProperties.FirstOrDefault(x => x.Name == sourceProperty.Name); 24 | if (targetProperty == null) 25 | continue; 26 | 27 | MapProperty(sourceProperty, source, target, targetProperty); 28 | } 29 | } 30 | } 31 | 32 | /// 33 | /// Verilen kaynak nesneyi hedef nesne yaratarak nesnenin özelliklerine set eder. 34 | /// 35 | /// Kaynak 36 | public static T Map(object source) where T : class 37 | { 38 | if (source == null) 39 | return null; 40 | 41 | object target = Activator.CreateInstance(typeof(T)); 42 | PropertyInfo[] targetProperties = target.GetType().GetProperties(); 43 | 44 | foreach (var sourceProperty in source.GetType().GetProperties()) 45 | { 46 | PropertyInfo targetProperty = targetProperties.FirstOrDefault(x => x.Name == sourceProperty.Name); 47 | if (targetProperty == null) 48 | continue; 49 | 50 | MapProperty(sourceProperty, source, target, targetProperty); 51 | } 52 | return (T)target; 53 | } 54 | 55 | /// 56 | /// Verilen kaynak nesneyi hedef nesne listesini yaratarak nesnenin özelliklerine set eder. 57 | /// 58 | /// kaynak tipi 59 | /// hedef tipi 60 | /// kaynak 61 | /// yeni bir klonlanmış hedef listesi 62 | /// 63 | public static List MapList(List sourceList) where TDestination : new() 64 | { 65 | if (sourceList == null) 66 | return null; 67 | 68 | List destinationList = new List(); 69 | foreach (var source in sourceList) 70 | { 71 | TDestination destinationItem = new TDestination(); 72 | foreach (var sourceProperty in source.GetType().GetProperties()) 73 | { 74 | PropertyInfo targetProperty = destinationItem.GetType().GetProperty(sourceProperty.Name); 75 | if (targetProperty == null) 76 | continue; 77 | 78 | if (sourceProperty.PropertyType.IsPrimitive || sourceProperty.PropertyType == typeof(string) || sourceProperty.PropertyType.IsValueType) 79 | { 80 | MapProperty(sourceProperty, source, destinationItem, targetProperty); 81 | } 82 | else if (sourceProperty.PropertyType.IsGenericType && sourceProperty.PropertyType.GetGenericTypeDefinition() == typeof(List<>)) 83 | { 84 | var tempSourceList = (IList)sourceProperty.GetValue(source); 85 | if (tempSourceList == null) 86 | continue; 87 | 88 | var listGenericType = sourceProperty.PropertyType.GetGenericArguments()[0]; 89 | 90 | if (sourceProperty.PropertyType.GetGenericArguments().Length != 1) 91 | throw new Exception($"Model içerisindeki {sourceProperty?.Name} isimli liste tek tipli olmalı!"); 92 | 93 | var listType = typeof(List<>).MakeGenericType(listGenericType); 94 | var clonedList = (IList)Activator.CreateInstance(listType); 95 | 96 | foreach (var item in tempSourceList) 97 | { 98 | clonedList.Add(item); 99 | } 100 | 101 | MapProperty(sourceProperty, clonedList, destinationItem, targetProperty, clonedList); 102 | } 103 | } 104 | 105 | destinationList.Add(destinationItem); 106 | } 107 | 108 | return destinationList; 109 | } 110 | 111 | /// 112 | /// Verilen kaynak nesneyi hedef nesnenin özelliklerine set eder. Exclude parametresi ile verilen özellikler atanmaz. 113 | /// 114 | /// Hedef 115 | /// Kaynak 116 | /// Atanmayacak Özellikler 117 | public static void MapExclude(object target, object source, params string[] exclude) 118 | { 119 | if (source != null && target != null) 120 | { 121 | PropertyInfo[] targetProperties = target.GetType().GetProperties(); 122 | foreach (var sourceProperty in source.GetType().GetProperties()) 123 | { 124 | if (exclude.Contains(sourceProperty.Name)) 125 | continue; 126 | 127 | PropertyInfo targetProperty = targetProperties.FirstOrDefault(x => x.Name == sourceProperty.Name); 128 | if (targetProperty == null) 129 | continue; 130 | 131 | MapProperty(sourceProperty, source, target, targetProperty); 132 | } 133 | } 134 | } 135 | 136 | /// 137 | /// Propertyinin değerini set eder. 138 | /// 139 | /// 140 | /// 141 | /// 142 | /// 143 | /// liste tipleri için önceden hazırlanmış değerleri. 144 | private static void MapProperty(PropertyInfo sourceProperty, object source, object target, PropertyInfo targetProperty, object sourceValue = null) 145 | { 146 | if (source == null) 147 | { 148 | return; 149 | } 150 | 151 | if (sourceProperty.CanRead && targetProperty.CanWrite) 152 | { 153 | sourceValue = sourceValue ?? sourceProperty.GetValue(source); 154 | if (targetProperty.PropertyType == sourceProperty.PropertyType && sourceValue != null) 155 | targetProperty.SetValue(target, sourceValue); 156 | } 157 | } 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /DMicroservices/Utils/RestSharp/CustomRestClient.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | using DMicroservices.Utils.Logger; 3 | using RestSharp; 4 | 5 | namespace DMicroservices.Utils.RestSharp 6 | { 7 | public class CustomRestClient : RestClient 8 | { 9 | private string _baseUrl; 10 | public CustomRestClient(string baseUrl) : base(baseUrl) 11 | { 12 | _baseUrl = baseUrl; 13 | } 14 | 15 | public override IRestResponse Execute(IRestRequest request) 16 | { 17 | var result = base.Execute(request); 18 | if (result.StatusCode != HttpStatusCode.OK) 19 | { 20 | ElasticLogger.Instance.Info($"Request not OK. Requested Url : {_baseUrl} Status Code : {result.StatusCode} Content : {result.Content} "); 21 | } 22 | return result; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dmicroservices 2 | DMicroservices Pack Project 3 | DMicroservices projesinin paketlenmiş halidir. 4 | Kolayca dotnet microservisleri oluşturulabilir kod bütünlüğüdür. 5 | -------------------------------------------------------------------------------- /Tests/DMicroservices.DataAccess.Tests/DMicroservices.DataAccess.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net5.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Tests/DMicroservices.DataAccess.Tests/MasterContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | using System.Text; 5 | using DMicroservices.DataAccess.Tests.Models; 6 | using DMicroservices.DataAccess.UnitOfWork; 7 | using Microsoft.EntityFrameworkCore; 8 | 9 | namespace DMicroservices.DataAccess.Tests 10 | { 11 | public class MasterContext : DbContext, ICustomDbContext 12 | { 13 | public MasterContext() 14 | { 15 | 16 | } 17 | public MasterContext(DbContextOptions options) 18 | { 19 | } 20 | 21 | public DbSet City { get; set; } 22 | public DbSet Person { get; set; } 23 | public DbSet Student { get; set; } 24 | public DbSet Teacher { get; set; } 25 | 26 | public DbSet Search { get; set; } 27 | 28 | protected override void OnModelCreating(ModelBuilder modelBuilder) 29 | { 30 | 31 | modelBuilder.Entity().HasOne(x => x.City).WithMany(x => x.Persons).HasForeignKey(x => x.ForeignCityId).HasPrincipalKey(x => x.Id); 32 | } 33 | 34 | 35 | protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) 36 | { 37 | if (!optionsBuilder.IsConfigured) 38 | { 39 | ServerVersion serverVersion; 40 | try 41 | { 42 | serverVersion = ServerVersion.AutoDetect(MYSQL_URI); 43 | } 44 | catch 45 | { 46 | serverVersion = ServerVersion.FromString("8.0.23"); 47 | } 48 | optionsBuilder.UseMySql(MYSQL_URI, serverVersion); 49 | optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking); 50 | } 51 | base.OnConfiguring(optionsBuilder); 52 | } 53 | 54 | public string MYSQL_URI { get; set; } = Environment.GetEnvironmentVariable("MYSQL_URI"); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Tests/DMicroservices.DataAccess.Tests/Migrations/20210125133956_v1.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using DMicroservices.DataAccess.Tests; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | using Microsoft.EntityFrameworkCore.Migrations; 6 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 7 | 8 | namespace DMicroservices.DataAccess.Tests.Migrations 9 | { 10 | [DbContext(typeof(MasterContext))] 11 | [Migration("20210125133956_v1")] 12 | partial class v1 13 | { 14 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 15 | { 16 | #pragma warning disable 612, 618 17 | modelBuilder 18 | .HasAnnotation("Relational:MaxIdentifierLength", 64) 19 | .HasAnnotation("ProductVersion", "5.0.1"); 20 | 21 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.City", b => 22 | { 23 | b.Property("Id") 24 | .ValueGeneratedOnAdd() 25 | .HasColumnType("bigint"); 26 | 27 | b.Property("Name") 28 | .HasColumnType("longtext CHARACTER SET utf8mb4"); 29 | 30 | b.HasKey("Id"); 31 | 32 | b.ToTable("City"); 33 | }); 34 | 35 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Person", b => 36 | { 37 | b.Property("Id") 38 | .ValueGeneratedOnAdd() 39 | .HasColumnType("bigint"); 40 | 41 | b.Property("ForeignCityId") 42 | .HasColumnType("bigint"); 43 | 44 | b.Property("Name") 45 | .HasColumnType("longtext CHARACTER SET utf8mb4"); 46 | 47 | b.HasKey("Id"); 48 | 49 | b.HasIndex("ForeignCityId"); 50 | 51 | b.ToTable("Person"); 52 | }); 53 | 54 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Student", b => 55 | { 56 | b.HasBaseType("DMicroservices.DataAccess.Tests.Models.Person"); 57 | 58 | b.Property("StudentNum") 59 | .HasColumnType("bigint"); 60 | 61 | b.ToTable("Student"); 62 | }); 63 | 64 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Teacher", b => 65 | { 66 | b.HasBaseType("DMicroservices.DataAccess.Tests.Models.Person"); 67 | 68 | b.Property("Branch") 69 | .HasColumnType("int"); 70 | 71 | b.ToTable("Teacher"); 72 | }); 73 | 74 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Person", b => 75 | { 76 | b.HasOne("DMicroservices.DataAccess.Tests.Models.City", "City") 77 | .WithMany("Persons") 78 | .HasForeignKey("ForeignCityId") 79 | .OnDelete(DeleteBehavior.Cascade) 80 | .IsRequired(); 81 | 82 | b.Navigation("City"); 83 | }); 84 | 85 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Student", b => 86 | { 87 | b.HasOne("DMicroservices.DataAccess.Tests.Models.Person", null) 88 | .WithOne() 89 | .HasForeignKey("DMicroservices.DataAccess.Tests.Models.Student", "Id") 90 | .OnDelete(DeleteBehavior.Cascade) 91 | .IsRequired(); 92 | }); 93 | 94 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Teacher", b => 95 | { 96 | b.HasOne("DMicroservices.DataAccess.Tests.Models.Person", null) 97 | .WithOne() 98 | .HasForeignKey("DMicroservices.DataAccess.Tests.Models.Teacher", "Id") 99 | .OnDelete(DeleteBehavior.Cascade) 100 | .IsRequired(); 101 | }); 102 | 103 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.City", b => 104 | { 105 | b.Navigation("Persons"); 106 | }); 107 | #pragma warning restore 612, 618 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /Tests/DMicroservices.DataAccess.Tests/Migrations/20210125133956_v1.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Metadata; 2 | using Microsoft.EntityFrameworkCore.Migrations; 3 | 4 | namespace DMicroservices.DataAccess.Tests.Migrations 5 | { 6 | public partial class v1 : Migration 7 | { 8 | protected override void Up(MigrationBuilder migrationBuilder) 9 | { 10 | migrationBuilder.CreateTable( 11 | name: "City", 12 | columns: table => new 13 | { 14 | Id = table.Column(type: "bigint", nullable: false) 15 | .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), 16 | Name = table.Column(type: "longtext CHARACTER SET utf8mb4", nullable: true) 17 | }, 18 | constraints: table => 19 | { 20 | table.PrimaryKey("PK_City", x => x.Id); 21 | }); 22 | 23 | migrationBuilder.CreateTable( 24 | name: "Person", 25 | columns: table => new 26 | { 27 | Id = table.Column(type: "bigint", nullable: false) 28 | .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), 29 | Name = table.Column(type: "longtext CHARACTER SET utf8mb4", nullable: true), 30 | ForeignCityId = table.Column(type: "bigint", nullable: false) 31 | }, 32 | constraints: table => 33 | { 34 | table.PrimaryKey("PK_Person", x => x.Id); 35 | table.ForeignKey( 36 | name: "FK_Person_City_ForeignCityId", 37 | column: x => x.ForeignCityId, 38 | principalTable: "City", 39 | principalColumn: "Id", 40 | onDelete: ReferentialAction.Cascade); 41 | }); 42 | 43 | migrationBuilder.CreateTable( 44 | name: "Student", 45 | columns: table => new 46 | { 47 | Id = table.Column(type: "bigint", nullable: false) 48 | .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), 49 | StudentNum = table.Column(type: "bigint", nullable: false) 50 | }, 51 | constraints: table => 52 | { 53 | table.PrimaryKey("PK_Student", x => x.Id); 54 | table.ForeignKey( 55 | name: "FK_Student_Person_Id", 56 | column: x => x.Id, 57 | principalTable: "Person", 58 | principalColumn: "Id", 59 | onDelete: ReferentialAction.Cascade); 60 | }); 61 | 62 | migrationBuilder.CreateTable( 63 | name: "Teacher", 64 | columns: table => new 65 | { 66 | Id = table.Column(type: "bigint", nullable: false) 67 | .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), 68 | Branch = table.Column(type: "int", nullable: false) 69 | }, 70 | constraints: table => 71 | { 72 | table.PrimaryKey("PK_Teacher", x => x.Id); 73 | table.ForeignKey( 74 | name: "FK_Teacher_Person_Id", 75 | column: x => x.Id, 76 | principalTable: "Person", 77 | principalColumn: "Id", 78 | onDelete: ReferentialAction.Cascade); 79 | }); 80 | 81 | migrationBuilder.CreateIndex( 82 | name: "IX_Person_ForeignCityId", 83 | table: "Person", 84 | column: "ForeignCityId"); 85 | } 86 | 87 | protected override void Down(MigrationBuilder migrationBuilder) 88 | { 89 | migrationBuilder.DropTable( 90 | name: "Student"); 91 | 92 | migrationBuilder.DropTable( 93 | name: "Teacher"); 94 | 95 | migrationBuilder.DropTable( 96 | name: "Person"); 97 | 98 | migrationBuilder.DropTable( 99 | name: "City"); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /Tests/DMicroservices.DataAccess.Tests/Migrations/20210125143139_v2.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using DMicroservices.DataAccess.Tests; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | using Microsoft.EntityFrameworkCore.Migrations; 6 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 7 | 8 | namespace DMicroservices.DataAccess.Tests.Migrations 9 | { 10 | [DbContext(typeof(MasterContext))] 11 | [Migration("20210125143139_v2")] 12 | partial class v2 13 | { 14 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 15 | { 16 | #pragma warning disable 612, 618 17 | modelBuilder 18 | .HasAnnotation("Relational:MaxIdentifierLength", 64) 19 | .HasAnnotation("ProductVersion", "5.0.1"); 20 | 21 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.City", b => 22 | { 23 | b.Property("Id") 24 | .ValueGeneratedOnAdd() 25 | .HasColumnType("bigint"); 26 | 27 | b.Property("Name") 28 | .HasMaxLength(5) 29 | .HasColumnType("varchar(5) CHARACTER SET utf8mb4"); 30 | 31 | b.HasKey("Id"); 32 | 33 | b.ToTable("City"); 34 | }); 35 | 36 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Person", b => 37 | { 38 | b.Property("Id") 39 | .ValueGeneratedOnAdd() 40 | .HasColumnType("bigint"); 41 | 42 | b.Property("ForeignCityId") 43 | .HasColumnType("bigint"); 44 | 45 | b.Property("Name") 46 | .HasColumnType("longtext CHARACTER SET utf8mb4"); 47 | 48 | b.HasKey("Id"); 49 | 50 | b.HasIndex("ForeignCityId"); 51 | 52 | b.ToTable("Person"); 53 | }); 54 | 55 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Student", b => 56 | { 57 | b.HasBaseType("DMicroservices.DataAccess.Tests.Models.Person"); 58 | 59 | b.Property("StudentNum") 60 | .HasColumnType("bigint"); 61 | 62 | b.ToTable("Student"); 63 | }); 64 | 65 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Teacher", b => 66 | { 67 | b.HasBaseType("DMicroservices.DataAccess.Tests.Models.Person"); 68 | 69 | b.Property("Branch") 70 | .HasColumnType("int"); 71 | 72 | b.ToTable("Teacher"); 73 | }); 74 | 75 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Person", b => 76 | { 77 | b.HasOne("DMicroservices.DataAccess.Tests.Models.City", "City") 78 | .WithMany("Persons") 79 | .HasForeignKey("ForeignCityId") 80 | .OnDelete(DeleteBehavior.Cascade) 81 | .IsRequired(); 82 | 83 | b.Navigation("City"); 84 | }); 85 | 86 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Student", b => 87 | { 88 | b.HasOne("DMicroservices.DataAccess.Tests.Models.Person", null) 89 | .WithOne() 90 | .HasForeignKey("DMicroservices.DataAccess.Tests.Models.Student", "Id") 91 | .OnDelete(DeleteBehavior.Cascade) 92 | .IsRequired(); 93 | }); 94 | 95 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Teacher", b => 96 | { 97 | b.HasOne("DMicroservices.DataAccess.Tests.Models.Person", null) 98 | .WithOne() 99 | .HasForeignKey("DMicroservices.DataAccess.Tests.Models.Teacher", "Id") 100 | .OnDelete(DeleteBehavior.Cascade) 101 | .IsRequired(); 102 | }); 103 | 104 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.City", b => 105 | { 106 | b.Navigation("Persons"); 107 | }); 108 | #pragma warning restore 612, 618 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /Tests/DMicroservices.DataAccess.Tests/Migrations/20210125143139_v2.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | 3 | namespace DMicroservices.DataAccess.Tests.Migrations 4 | { 5 | public partial class v2 : Migration 6 | { 7 | protected override void Up(MigrationBuilder migrationBuilder) 8 | { 9 | migrationBuilder.AlterColumn( 10 | name: "Name", 11 | table: "City", 12 | type: "varchar(5) CHARACTER SET utf8mb4", 13 | maxLength: 5, 14 | nullable: true, 15 | oldClrType: typeof(string), 16 | oldType: "longtext CHARACTER SET utf8mb4", 17 | oldNullable: true); 18 | } 19 | 20 | protected override void Down(MigrationBuilder migrationBuilder) 21 | { 22 | migrationBuilder.AlterColumn( 23 | name: "Name", 24 | table: "City", 25 | type: "longtext CHARACTER SET utf8mb4", 26 | nullable: true, 27 | oldClrType: typeof(string), 28 | oldType: "varchar(5) CHARACTER SET utf8mb4", 29 | oldMaxLength: 5, 30 | oldNullable: true); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Tests/DMicroservices.DataAccess.Tests/Migrations/20210208080618_v3.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using DMicroservices.DataAccess.Tests; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore.Infrastructure; 6 | using Microsoft.EntityFrameworkCore.Migrations; 7 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 8 | 9 | namespace DMicroservices.DataAccess.Tests.Migrations 10 | { 11 | [DbContext(typeof(MasterContext))] 12 | [Migration("20210208080618_v3")] 13 | partial class v3 14 | { 15 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 16 | { 17 | #pragma warning disable 612, 618 18 | modelBuilder 19 | .HasAnnotation("Relational:MaxIdentifierLength", 64) 20 | .HasAnnotation("ProductVersion", "5.0.1"); 21 | 22 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.City", b => 23 | { 24 | b.Property("Id") 25 | .ValueGeneratedOnAdd() 26 | .HasColumnType("bigint"); 27 | 28 | b.Property("Name") 29 | .HasMaxLength(5) 30 | .HasColumnType("varchar(5) CHARACTER SET utf8mb4"); 31 | 32 | b.HasKey("Id"); 33 | 34 | b.ToTable("City"); 35 | }); 36 | 37 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Person", b => 38 | { 39 | b.Property("Id") 40 | .ValueGeneratedOnAdd() 41 | .HasColumnType("bigint"); 42 | 43 | b.Property("ForeignCityId") 44 | .HasColumnType("bigint"); 45 | 46 | b.Property("Name") 47 | .HasColumnType("longtext CHARACTER SET utf8mb4"); 48 | 49 | b.HasKey("Id"); 50 | 51 | b.HasIndex("ForeignCityId"); 52 | 53 | b.ToTable("Person"); 54 | }); 55 | 56 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Search", b => 57 | { 58 | b.Property("Id") 59 | .ValueGeneratedOnAdd() 60 | .HasColumnType("int"); 61 | 62 | b.Property("BigIntValue") 63 | .HasColumnType("bigint"); 64 | 65 | b.Property("BoolValue") 66 | .HasColumnType("tinyint(1)"); 67 | 68 | b.Property("ByteValue") 69 | .HasColumnType("tinyint unsigned"); 70 | 71 | b.Property("DateTimeValue") 72 | .HasColumnType("datetime(6)"); 73 | 74 | b.Property("DecimalValue") 75 | .HasColumnType("decimal(65,30)"); 76 | 77 | b.Property("DoubleValue") 78 | .HasColumnType("double"); 79 | 80 | b.Property("EnumValue") 81 | .HasColumnType("smallint"); 82 | 83 | b.Property("GuidNullableValue") 84 | .HasColumnType("char(36)"); 85 | 86 | b.Property("GuidValue") 87 | .HasColumnType("char(36)"); 88 | 89 | b.Property("IntNullableValue") 90 | .HasColumnType("int"); 91 | 92 | b.Property("IntValue") 93 | .HasColumnType("int"); 94 | 95 | b.Property("SmallIntValue") 96 | .HasColumnType("smallint"); 97 | 98 | b.Property("StringValue") 99 | .HasColumnType("longtext CHARACTER SET utf8mb4"); 100 | 101 | b.HasKey("Id"); 102 | 103 | b.ToTable("Search"); 104 | }); 105 | 106 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Student", b => 107 | { 108 | b.HasBaseType("DMicroservices.DataAccess.Tests.Models.Person"); 109 | 110 | b.Property("StudentNum") 111 | .HasColumnType("bigint"); 112 | 113 | b.ToTable("Student"); 114 | }); 115 | 116 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Teacher", b => 117 | { 118 | b.HasBaseType("DMicroservices.DataAccess.Tests.Models.Person"); 119 | 120 | b.Property("Branch") 121 | .HasColumnType("int"); 122 | 123 | b.ToTable("Teacher"); 124 | }); 125 | 126 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Person", b => 127 | { 128 | b.HasOne("DMicroservices.DataAccess.Tests.Models.City", "City") 129 | .WithMany("Persons") 130 | .HasForeignKey("ForeignCityId") 131 | .OnDelete(DeleteBehavior.Cascade) 132 | .IsRequired(); 133 | 134 | b.Navigation("City"); 135 | }); 136 | 137 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Student", b => 138 | { 139 | b.HasOne("DMicroservices.DataAccess.Tests.Models.Person", null) 140 | .WithOne() 141 | .HasForeignKey("DMicroservices.DataAccess.Tests.Models.Student", "Id") 142 | .OnDelete(DeleteBehavior.Cascade) 143 | .IsRequired(); 144 | }); 145 | 146 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Teacher", b => 147 | { 148 | b.HasOne("DMicroservices.DataAccess.Tests.Models.Person", null) 149 | .WithOne() 150 | .HasForeignKey("DMicroservices.DataAccess.Tests.Models.Teacher", "Id") 151 | .OnDelete(DeleteBehavior.Cascade) 152 | .IsRequired(); 153 | }); 154 | 155 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.City", b => 156 | { 157 | b.Navigation("Persons"); 158 | }); 159 | #pragma warning restore 612, 618 160 | } 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /Tests/DMicroservices.DataAccess.Tests/Migrations/20210208080618_v3.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore.Metadata; 3 | using Microsoft.EntityFrameworkCore.Migrations; 4 | 5 | namespace DMicroservices.DataAccess.Tests.Migrations 6 | { 7 | public partial class v3 : Migration 8 | { 9 | protected override void Up(MigrationBuilder migrationBuilder) 10 | { 11 | migrationBuilder.CreateTable( 12 | name: "Search", 13 | columns: table => new 14 | { 15 | Id = table.Column(type: "int", nullable: false) 16 | .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), 17 | IntValue = table.Column(type: "int", nullable: false), 18 | IntNullableValue = table.Column(type: "int", nullable: true), 19 | StringValue = table.Column(type: "longtext CHARACTER SET utf8mb4", nullable: true), 20 | DecimalValue = table.Column(type: "decimal(65,30)", nullable: false), 21 | SmallIntValue = table.Column(type: "smallint", nullable: false), 22 | BigIntValue = table.Column(type: "bigint", nullable: false), 23 | ByteValue = table.Column(type: "tinyint unsigned", nullable: false), 24 | DateTimeValue = table.Column(type: "datetime(6)", nullable: false), 25 | BoolValue = table.Column(type: "tinyint(1)", nullable: false), 26 | DoubleValue = table.Column(type: "double", nullable: false), 27 | EnumValue = table.Column(type: "smallint", nullable: false), 28 | GuidValue = table.Column(type: "char(36)", nullable: false), 29 | GuidNullableValue = table.Column(type: "char(36)", nullable: true) 30 | }, 31 | constraints: table => 32 | { 33 | table.PrimaryKey("PK_Search", x => x.Id); 34 | }); 35 | } 36 | 37 | protected override void Down(MigrationBuilder migrationBuilder) 38 | { 39 | migrationBuilder.DropTable( 40 | name: "Search"); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Tests/DMicroservices.DataAccess.Tests/Migrations/20220427093400_v5.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using DMicroservices.DataAccess.Tests; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore.Infrastructure; 6 | using Microsoft.EntityFrameworkCore.Migrations; 7 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 8 | 9 | namespace DMicroservices.DataAccess.Tests.Migrations 10 | { 11 | [DbContext(typeof(MasterContext))] 12 | [Migration("20220427093400_v5")] 13 | partial class v5 14 | { 15 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 16 | { 17 | #pragma warning disable 612, 618 18 | modelBuilder 19 | .HasAnnotation("Relational:MaxIdentifierLength", 64) 20 | .HasAnnotation("ProductVersion", "5.0.1"); 21 | 22 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.City", b => 23 | { 24 | b.Property("Id") 25 | .ValueGeneratedOnAdd() 26 | .HasColumnType("bigint"); 27 | 28 | b.Property("Name") 29 | .HasMaxLength(5) 30 | .HasColumnType("varchar(5) CHARACTER SET utf8mb4"); 31 | 32 | b.HasKey("Id"); 33 | 34 | b.ToTable("City"); 35 | }); 36 | 37 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Person", b => 38 | { 39 | b.Property("Id") 40 | .ValueGeneratedOnAdd() 41 | .HasColumnType("bigint"); 42 | 43 | b.Property("ForeignCityId") 44 | .HasColumnType("bigint"); 45 | 46 | b.Property("Name") 47 | .HasColumnType("longtext CHARACTER SET utf8mb4"); 48 | 49 | b.HasKey("Id"); 50 | 51 | b.HasIndex("ForeignCityId"); 52 | 53 | b.ToTable("Person"); 54 | }); 55 | 56 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Search", b => 57 | { 58 | b.Property("Id") 59 | .ValueGeneratedOnAdd() 60 | .HasColumnType("int"); 61 | 62 | b.Property("BigIntValue") 63 | .HasColumnType("bigint"); 64 | 65 | b.Property("BoolValue") 66 | .HasColumnType("tinyint(1)"); 67 | 68 | b.Property("ByteValue") 69 | .HasColumnType("tinyint unsigned"); 70 | 71 | b.Property("DateTimeNullable") 72 | .HasColumnType("datetime(6)"); 73 | 74 | b.Property("DateTimeValue") 75 | .HasColumnType("datetime(6)"); 76 | 77 | b.Property("DecimalValue") 78 | .HasColumnType("decimal(65,30)"); 79 | 80 | b.Property("DoubleValue") 81 | .HasColumnType("double"); 82 | 83 | b.Property("EnumValue") 84 | .HasColumnType("smallint"); 85 | 86 | b.Property("GuidNullableValue") 87 | .HasColumnType("char(36)"); 88 | 89 | b.Property("GuidValue") 90 | .HasColumnType("char(36)"); 91 | 92 | b.Property("IntNullableValue") 93 | .HasColumnType("int"); 94 | 95 | b.Property("IntValue") 96 | .HasColumnType("int"); 97 | 98 | b.Property("SmallIntValue") 99 | .HasColumnType("smallint"); 100 | 101 | b.Property("StringValue") 102 | .HasColumnType("longtext CHARACTER SET utf8mb4"); 103 | 104 | b.HasKey("Id"); 105 | 106 | b.ToTable("Search"); 107 | }); 108 | 109 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Student", b => 110 | { 111 | b.HasBaseType("DMicroservices.DataAccess.Tests.Models.Person"); 112 | 113 | b.Property("StudentNum") 114 | .HasColumnType("bigint"); 115 | 116 | b.ToTable("Student"); 117 | }); 118 | 119 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Teacher", b => 120 | { 121 | b.HasBaseType("DMicroservices.DataAccess.Tests.Models.Person"); 122 | 123 | b.Property("Branch") 124 | .HasColumnType("int"); 125 | 126 | b.ToTable("Teacher"); 127 | }); 128 | 129 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Person", b => 130 | { 131 | b.HasOne("DMicroservices.DataAccess.Tests.Models.City", "City") 132 | .WithMany("Persons") 133 | .HasForeignKey("ForeignCityId") 134 | .OnDelete(DeleteBehavior.Cascade) 135 | .IsRequired(); 136 | 137 | b.Navigation("City"); 138 | }); 139 | 140 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Student", b => 141 | { 142 | b.HasOne("DMicroservices.DataAccess.Tests.Models.Person", null) 143 | .WithOne() 144 | .HasForeignKey("DMicroservices.DataAccess.Tests.Models.Student", "Id") 145 | .OnDelete(DeleteBehavior.Cascade) 146 | .IsRequired(); 147 | }); 148 | 149 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Teacher", b => 150 | { 151 | b.HasOne("DMicroservices.DataAccess.Tests.Models.Person", null) 152 | .WithOne() 153 | .HasForeignKey("DMicroservices.DataAccess.Tests.Models.Teacher", "Id") 154 | .OnDelete(DeleteBehavior.Cascade) 155 | .IsRequired(); 156 | }); 157 | 158 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.City", b => 159 | { 160 | b.Navigation("Persons"); 161 | }); 162 | #pragma warning restore 612, 618 163 | } 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /Tests/DMicroservices.DataAccess.Tests/Migrations/20220427093400_v5.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore.Migrations; 3 | 4 | namespace DMicroservices.DataAccess.Tests.Migrations 5 | { 6 | public partial class v5 : Migration 7 | { 8 | protected override void Up(MigrationBuilder migrationBuilder) 9 | { 10 | migrationBuilder.AddColumn( 11 | name: "DateTimeNullable", 12 | table: "Search", 13 | type: "datetime(6)", 14 | nullable: true); 15 | } 16 | 17 | protected override void Down(MigrationBuilder migrationBuilder) 18 | { 19 | migrationBuilder.DropColumn( 20 | name: "DateTimeNullable", 21 | table: "Search"); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Tests/DMicroservices.DataAccess.Tests/Migrations/20221017124037_v6.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using DMicroservices.DataAccess.Tests; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore.Infrastructure; 6 | using Microsoft.EntityFrameworkCore.Migrations; 7 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 8 | 9 | namespace DMicroservices.DataAccess.Tests.Migrations 10 | { 11 | [DbContext(typeof(MasterContext))] 12 | [Migration("20221017124037_v6")] 13 | partial class v6 14 | { 15 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 16 | { 17 | #pragma warning disable 612, 618 18 | modelBuilder 19 | .HasAnnotation("Relational:MaxIdentifierLength", 64) 20 | .HasAnnotation("ProductVersion", "5.0.1"); 21 | 22 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.City", b => 23 | { 24 | b.Property("Id") 25 | .ValueGeneratedOnAdd() 26 | .HasColumnType("bigint"); 27 | 28 | b.Property("Name") 29 | .HasMaxLength(5) 30 | .HasColumnType("varchar(5) CHARACTER SET utf8mb4"); 31 | 32 | b.HasKey("Id"); 33 | 34 | b.ToTable("City"); 35 | }); 36 | 37 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Person", b => 38 | { 39 | b.Property("Id") 40 | .ValueGeneratedOnAdd() 41 | .HasColumnType("bigint"); 42 | 43 | b.Property("ForeignCityId") 44 | .HasColumnType("bigint"); 45 | 46 | b.Property("Name") 47 | .HasColumnType("longtext CHARACTER SET utf8mb4"); 48 | 49 | b.HasKey("Id"); 50 | 51 | b.HasIndex("ForeignCityId"); 52 | 53 | b.ToTable("Person"); 54 | }); 55 | 56 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Search", b => 57 | { 58 | b.Property("Id") 59 | .ValueGeneratedOnAdd() 60 | .HasColumnType("int"); 61 | 62 | b.Property("BigIntValue") 63 | .HasColumnType("bigint"); 64 | 65 | b.Property("BoolValue") 66 | .HasColumnType("tinyint(1)"); 67 | 68 | b.Property("ByteValue") 69 | .HasColumnType("tinyint unsigned"); 70 | 71 | b.Property("DateTimeNullable") 72 | .HasColumnType("datetime(6)"); 73 | 74 | b.Property("DateTimeValue") 75 | .HasColumnType("datetime(6)"); 76 | 77 | b.Property("DecimalValue") 78 | .HasColumnType("decimal(65,30)"); 79 | 80 | b.Property("DoubleValue") 81 | .HasColumnType("double"); 82 | 83 | b.Property("EnumValue") 84 | .HasColumnType("smallint"); 85 | 86 | b.Property("GuidNullableValue") 87 | .HasColumnType("char(36)"); 88 | 89 | b.Property("GuidValue") 90 | .HasColumnType("char(36)"); 91 | 92 | b.Property("IntNullableValue") 93 | .HasColumnType("int"); 94 | 95 | b.Property("IntValue") 96 | .HasColumnType("int"); 97 | 98 | b.Property("SmallIntValue") 99 | .HasColumnType("smallint"); 100 | 101 | b.Property("StringValue") 102 | .HasColumnType("longtext CHARACTER SET utf8mb4"); 103 | 104 | b.HasKey("Id"); 105 | 106 | b.ToTable("Search"); 107 | }); 108 | 109 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Student", b => 110 | { 111 | b.HasBaseType("DMicroservices.DataAccess.Tests.Models.Person"); 112 | 113 | b.Property("StudentNum") 114 | .HasColumnType("bigint"); 115 | 116 | b.ToTable("Student"); 117 | }); 118 | 119 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Teacher", b => 120 | { 121 | b.HasBaseType("DMicroservices.DataAccess.Tests.Models.Person"); 122 | 123 | b.Property("Branch") 124 | .HasColumnType("int"); 125 | 126 | b.ToTable("Teacher"); 127 | }); 128 | 129 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Person", b => 130 | { 131 | b.HasOne("DMicroservices.DataAccess.Tests.Models.City", "City") 132 | .WithMany("Persons") 133 | .HasForeignKey("ForeignCityId") 134 | .OnDelete(DeleteBehavior.Cascade) 135 | .IsRequired(); 136 | 137 | b.Navigation("City"); 138 | }); 139 | 140 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Student", b => 141 | { 142 | b.HasOne("DMicroservices.DataAccess.Tests.Models.Person", null) 143 | .WithOne() 144 | .HasForeignKey("DMicroservices.DataAccess.Tests.Models.Student", "Id") 145 | .OnDelete(DeleteBehavior.Cascade) 146 | .IsRequired(); 147 | }); 148 | 149 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Teacher", b => 150 | { 151 | b.HasOne("DMicroservices.DataAccess.Tests.Models.Person", null) 152 | .WithOne() 153 | .HasForeignKey("DMicroservices.DataAccess.Tests.Models.Teacher", "Id") 154 | .OnDelete(DeleteBehavior.Cascade) 155 | .IsRequired(); 156 | }); 157 | 158 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.City", b => 159 | { 160 | b.Navigation("Persons"); 161 | }); 162 | #pragma warning restore 612, 618 163 | } 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /Tests/DMicroservices.DataAccess.Tests/Migrations/20221017124037_v6.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | 3 | namespace DMicroservices.DataAccess.Tests.Migrations 4 | { 5 | public partial class v6 : Migration 6 | { 7 | protected override void Up(MigrationBuilder migrationBuilder) 8 | { 9 | 10 | } 11 | 12 | protected override void Down(MigrationBuilder migrationBuilder) 13 | { 14 | 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Tests/DMicroservices.DataAccess.Tests/Migrations/20230322133308_tet.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using DMicroservices.DataAccess.Tests; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore.Infrastructure; 6 | using Microsoft.EntityFrameworkCore.Migrations; 7 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 8 | 9 | namespace DMicroservices.DataAccess.Tests.Migrations 10 | { 11 | [DbContext(typeof(MasterContext))] 12 | [Migration("20230322133308_tet")] 13 | partial class tet 14 | { 15 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 16 | { 17 | #pragma warning disable 612, 618 18 | modelBuilder 19 | .HasAnnotation("Relational:MaxIdentifierLength", 64) 20 | .HasAnnotation("ProductVersion", "5.0.1"); 21 | 22 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.City", b => 23 | { 24 | b.Property("Id") 25 | .ValueGeneratedOnAdd() 26 | .HasColumnType("bigint"); 27 | 28 | b.Property("Name") 29 | .HasMaxLength(5) 30 | .HasColumnType("varchar(5) CHARACTER SET utf8mb4"); 31 | 32 | b.HasKey("Id"); 33 | 34 | b.ToTable("City"); 35 | }); 36 | 37 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Person", b => 38 | { 39 | b.Property("Id") 40 | .ValueGeneratedOnAdd() 41 | .HasColumnType("bigint"); 42 | 43 | b.Property("ForeignCityId") 44 | .HasColumnType("bigint"); 45 | 46 | b.Property("Name") 47 | .HasColumnType("longtext CHARACTER SET utf8mb4"); 48 | 49 | b.Property("SurName") 50 | .HasColumnType("longtext CHARACTER SET utf8mb4"); 51 | 52 | b.HasKey("Id"); 53 | 54 | b.HasIndex("ForeignCityId"); 55 | 56 | b.ToTable("Person"); 57 | }); 58 | 59 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Search", b => 60 | { 61 | b.Property("Id") 62 | .ValueGeneratedOnAdd() 63 | .HasColumnType("int"); 64 | 65 | b.Property("BigIntValue") 66 | .HasColumnType("bigint"); 67 | 68 | b.Property("BoolValue") 69 | .HasColumnType("tinyint(1)"); 70 | 71 | b.Property("ByteValue") 72 | .HasColumnType("tinyint unsigned"); 73 | 74 | b.Property("DateTimeNullable") 75 | .HasColumnType("datetime(6)"); 76 | 77 | b.Property("DateTimeValue") 78 | .HasColumnType("datetime(6)"); 79 | 80 | b.Property("DecimalValue") 81 | .HasColumnType("decimal(65,30)"); 82 | 83 | b.Property("DoubleValue") 84 | .HasColumnType("double"); 85 | 86 | b.Property("EnumValue") 87 | .HasColumnType("smallint"); 88 | 89 | b.Property("GuidNullableValue") 90 | .HasColumnType("char(36)"); 91 | 92 | b.Property("GuidValue") 93 | .HasColumnType("char(36)"); 94 | 95 | b.Property("IntNullableValue") 96 | .HasColumnType("int"); 97 | 98 | b.Property("IntValue") 99 | .HasColumnType("int"); 100 | 101 | b.Property("SmallIntValue") 102 | .HasColumnType("smallint"); 103 | 104 | b.Property("StringValue") 105 | .HasColumnType("longtext CHARACTER SET utf8mb4"); 106 | 107 | b.HasKey("Id"); 108 | 109 | b.ToTable("Search"); 110 | }); 111 | 112 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Student", b => 113 | { 114 | b.HasBaseType("DMicroservices.DataAccess.Tests.Models.Person"); 115 | 116 | b.Property("StudentNum") 117 | .HasColumnType("bigint"); 118 | 119 | b.ToTable("Student"); 120 | }); 121 | 122 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Teacher", b => 123 | { 124 | b.HasBaseType("DMicroservices.DataAccess.Tests.Models.Person"); 125 | 126 | b.Property("Branch") 127 | .HasColumnType("int"); 128 | 129 | b.ToTable("Teacher"); 130 | }); 131 | 132 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Person", b => 133 | { 134 | b.HasOne("DMicroservices.DataAccess.Tests.Models.City", "City") 135 | .WithMany("Persons") 136 | .HasForeignKey("ForeignCityId") 137 | .OnDelete(DeleteBehavior.Cascade) 138 | .IsRequired(); 139 | 140 | b.Navigation("City"); 141 | }); 142 | 143 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Student", b => 144 | { 145 | b.HasOne("DMicroservices.DataAccess.Tests.Models.Person", null) 146 | .WithOne() 147 | .HasForeignKey("DMicroservices.DataAccess.Tests.Models.Student", "Id") 148 | .OnDelete(DeleteBehavior.Cascade) 149 | .IsRequired(); 150 | }); 151 | 152 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Teacher", b => 153 | { 154 | b.HasOne("DMicroservices.DataAccess.Tests.Models.Person", null) 155 | .WithOne() 156 | .HasForeignKey("DMicroservices.DataAccess.Tests.Models.Teacher", "Id") 157 | .OnDelete(DeleteBehavior.Cascade) 158 | .IsRequired(); 159 | }); 160 | 161 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.City", b => 162 | { 163 | b.Navigation("Persons"); 164 | }); 165 | #pragma warning restore 612, 618 166 | } 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /Tests/DMicroservices.DataAccess.Tests/Migrations/20230322133308_tet.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | 3 | namespace DMicroservices.DataAccess.Tests.Migrations 4 | { 5 | public partial class tet : Migration 6 | { 7 | protected override void Up(MigrationBuilder migrationBuilder) 8 | { 9 | migrationBuilder.AddColumn( 10 | name: "SurName", 11 | table: "Person", 12 | type: "longtext CHARACTER SET utf8mb4", 13 | nullable: true); 14 | } 15 | 16 | protected override void Down(MigrationBuilder migrationBuilder) 17 | { 18 | migrationBuilder.DropColumn( 19 | name: "SurName", 20 | table: "Person"); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Tests/DMicroservices.DataAccess.Tests/Migrations/MasterContextModelSnapshot.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using DMicroservices.DataAccess.Tests; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore.Infrastructure; 6 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 7 | 8 | namespace DMicroservices.DataAccess.Tests.Migrations 9 | { 10 | [DbContext(typeof(MasterContext))] 11 | partial class MasterContextModelSnapshot : ModelSnapshot 12 | { 13 | protected override void BuildModel(ModelBuilder modelBuilder) 14 | { 15 | #pragma warning disable 612, 618 16 | modelBuilder 17 | .HasAnnotation("Relational:MaxIdentifierLength", 64) 18 | .HasAnnotation("ProductVersion", "5.0.1"); 19 | 20 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.City", b => 21 | { 22 | b.Property("Id") 23 | .ValueGeneratedOnAdd() 24 | .HasColumnType("bigint"); 25 | 26 | b.Property("Name") 27 | .HasMaxLength(5) 28 | .HasColumnType("varchar(5) CHARACTER SET utf8mb4"); 29 | 30 | b.HasKey("Id"); 31 | 32 | b.ToTable("City"); 33 | }); 34 | 35 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Person", b => 36 | { 37 | b.Property("Id") 38 | .ValueGeneratedOnAdd() 39 | .HasColumnType("bigint"); 40 | 41 | b.Property("ForeignCityId") 42 | .HasColumnType("bigint"); 43 | 44 | b.Property("Name") 45 | .HasColumnType("longtext CHARACTER SET utf8mb4"); 46 | 47 | b.Property("SurName") 48 | .HasColumnType("longtext CHARACTER SET utf8mb4"); 49 | 50 | b.HasKey("Id"); 51 | 52 | b.HasIndex("ForeignCityId"); 53 | 54 | b.ToTable("Person"); 55 | }); 56 | 57 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Search", b => 58 | { 59 | b.Property("Id") 60 | .ValueGeneratedOnAdd() 61 | .HasColumnType("int"); 62 | 63 | b.Property("BigIntValue") 64 | .HasColumnType("bigint"); 65 | 66 | b.Property("BoolValue") 67 | .HasColumnType("tinyint(1)"); 68 | 69 | b.Property("ByteValue") 70 | .HasColumnType("tinyint unsigned"); 71 | 72 | b.Property("DateTimeNullable") 73 | .HasColumnType("datetime(6)"); 74 | 75 | b.Property("DateTimeValue") 76 | .HasColumnType("datetime(6)"); 77 | 78 | b.Property("DecimalValue") 79 | .HasColumnType("decimal(65,30)"); 80 | 81 | b.Property("DoubleValue") 82 | .HasColumnType("double"); 83 | 84 | b.Property("EnumValue") 85 | .HasColumnType("smallint"); 86 | 87 | b.Property("GuidNullableValue") 88 | .HasColumnType("char(36)"); 89 | 90 | b.Property("GuidValue") 91 | .HasColumnType("char(36)"); 92 | 93 | b.Property("IntNullableValue") 94 | .HasColumnType("int"); 95 | 96 | b.Property("IntValue") 97 | .HasColumnType("int"); 98 | 99 | b.Property("SmallIntValue") 100 | .HasColumnType("smallint"); 101 | 102 | b.Property("StringValue") 103 | .HasColumnType("longtext CHARACTER SET utf8mb4"); 104 | 105 | b.HasKey("Id"); 106 | 107 | b.ToTable("Search"); 108 | }); 109 | 110 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Student", b => 111 | { 112 | b.HasBaseType("DMicroservices.DataAccess.Tests.Models.Person"); 113 | 114 | b.Property("StudentNum") 115 | .HasColumnType("bigint"); 116 | 117 | b.ToTable("Student"); 118 | }); 119 | 120 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Teacher", b => 121 | { 122 | b.HasBaseType("DMicroservices.DataAccess.Tests.Models.Person"); 123 | 124 | b.Property("Branch") 125 | .HasColumnType("int"); 126 | 127 | b.ToTable("Teacher"); 128 | }); 129 | 130 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Person", b => 131 | { 132 | b.HasOne("DMicroservices.DataAccess.Tests.Models.City", "City") 133 | .WithMany("Persons") 134 | .HasForeignKey("ForeignCityId") 135 | .OnDelete(DeleteBehavior.Cascade) 136 | .IsRequired(); 137 | 138 | b.Navigation("City"); 139 | }); 140 | 141 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Student", b => 142 | { 143 | b.HasOne("DMicroservices.DataAccess.Tests.Models.Person", null) 144 | .WithOne() 145 | .HasForeignKey("DMicroservices.DataAccess.Tests.Models.Student", "Id") 146 | .OnDelete(DeleteBehavior.Cascade) 147 | .IsRequired(); 148 | }); 149 | 150 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.Teacher", b => 151 | { 152 | b.HasOne("DMicroservices.DataAccess.Tests.Models.Person", null) 153 | .WithOne() 154 | .HasForeignKey("DMicroservices.DataAccess.Tests.Models.Teacher", "Id") 155 | .OnDelete(DeleteBehavior.Cascade) 156 | .IsRequired(); 157 | }); 158 | 159 | modelBuilder.Entity("DMicroservices.DataAccess.Tests.Models.City", b => 160 | { 161 | b.Navigation("Persons"); 162 | }); 163 | #pragma warning restore 612, 618 164 | } 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /Tests/DMicroservices.DataAccess.Tests/Models/City.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | using System.Text; 6 | 7 | namespace DMicroservices.DataAccess.Tests.Models 8 | { 9 | [Table("City")] 10 | public class City 11 | { 12 | [Key] 13 | [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 14 | public long Id { get; set; } 15 | 16 | [MaxLength(5)] 17 | public string Name { get; set; } 18 | 19 | public ICollection Persons { get; set; } 20 | 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Tests/DMicroservices.DataAccess.Tests/Models/Document.cs: -------------------------------------------------------------------------------- 1 | using MongoDB.Bson.Serialization.Attributes; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace DMicroservices.DataAccess.Tests.Models 7 | { 8 | public class Document 9 | { 10 | [BsonId] 11 | public string Id { get; set; } 12 | 13 | public byte[] Data { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Tests/DMicroservices.DataAccess.Tests/Models/Person.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | using System.Text; 6 | using DMicroservices.Base.Attributes; 7 | 8 | namespace DMicroservices.DataAccess.Tests.Models 9 | { 10 | [Table("Person")] 11 | public class Person 12 | { 13 | [Key] 14 | [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 15 | public long Id { get; set; } 16 | 17 | // [DisableChangeTrack] 18 | public string Name { get; set; } 19 | 20 | public string SurName { get; set; } 21 | 22 | public City City { get; set; } 23 | 24 | public long ForeignCityId { get; set; } 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Tests/DMicroservices.DataAccess.Tests/Models/Search.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Text; 5 | 6 | namespace DMicroservices.DataAccess.Tests.Models 7 | { 8 | public class Search 9 | { 10 | [Key] 11 | public int Id { get; set; } 12 | public int IntValue { get; set; } 13 | public int? IntNullableValue { get; set; } 14 | 15 | public string StringValue { get; set; } 16 | 17 | public decimal DecimalValue { get; set; } 18 | 19 | public short SmallIntValue { get; set; } 20 | 21 | public Int64 BigIntValue { get; set; } 22 | 23 | public byte ByteValue { get; set; } 24 | 25 | public DateTime DateTimeValue { get; set; } 26 | 27 | public DateTime? DateTimeNullable { get; set; } 28 | 29 | public bool BoolValue { get; set; } 30 | 31 | public double DoubleValue { get; set; } 32 | 33 | public Number EnumValue { get; set; } 34 | 35 | public Guid GuidValue { get; set; } 36 | 37 | public Guid? GuidNullableValue { get; set; } 38 | } 39 | 40 | public enum Number : short 41 | { 42 | One = 1, 43 | Two = 2 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Tests/DMicroservices.DataAccess.Tests/Models/Student.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | using System.Text; 6 | 7 | namespace DMicroservices.DataAccess.Tests.Models 8 | { 9 | [Table("Student")] 10 | public class Student : Person 11 | { 12 | public long StudentNum { get; set; } 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Tests/DMicroservices.DataAccess.Tests/Models/Teacher.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | using System.Text; 6 | 7 | namespace DMicroservices.DataAccess.Tests.Models 8 | { 9 | [Table("Teacher")] 10 | public class Teacher : Person 11 | { 12 | public int Branch { get; set; } 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Tests/DMicroservices.DataAccess.Tests/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "DMicroservices.DataAccess.Tests": { 4 | "commandName": "Project", 5 | "environmentVariables": { 6 | "MYSQL_URI": "server=127.0.0.1;port=13038;database=xyz;user=root;password=root;Max Pool Size=200;Min Pool Size=10;Pooling=true", 7 | "MYSQL_RO_URI": "server=127.0.0.2,127.0.0.1;port=30052;database=xyz;user=root;password=root;Max Pool Size=200;Min Pool Size=10;Pooling=true;LoadBalance=FailOver", 8 | "MONGO_URI": "mongodb://root:root@127.0.0.1:13033/?maxPoolSize=150&minPoolSize=25", 9 | "MONGO_DB_NAME": "DMicroservices", 10 | "THROW_UNIT_OF_WORK_ERROR": "true", 11 | "ELASTIC_URI": "http://localhost:13030", 12 | "LOG_INDEX_FORMAT": "serilog-{0:yyyy.MM.dd}", 13 | "REDIS_URL": "127.0.0.1:13036", 14 | "THROW_MONGO_ERROR": "false" 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /Tests/DMicroservices.RabbitMq.Test/DMicroservices.RabbitMq.Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Tests/DMicroservices.RabbitMq.Test/ExampleConsumer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using DMicroservices.RabbitMq.Base; 4 | using DMicroservices.RabbitMq.Consumer; 5 | using RabbitMQ.Client.Events; 6 | 7 | namespace DMicroservices.RabbitMq.Test 8 | { 9 | [ListenQueue(typeof(Test), "QueueName")] 10 | class ExampleConsumer : BasicConsumer 11 | { 12 | public override bool AutoAck => false; 13 | public override ushort PrefectCount { get => 10; } 14 | 15 | public override bool Durable => false; 16 | public override bool AutoDelete => true; 17 | 18 | public override Action DataReceivedAction => DataReceived; 19 | 20 | private void DataReceived(ExampleModel model, BasicDeliverEventArgs e) 21 | { 22 | Console.WriteLine(model.Message); 23 | 24 | Thread.Sleep(1000); 25 | //Send Ack. 26 | BasicAck(e.DeliveryTag, false); 27 | 28 | } 29 | 30 | } 31 | 32 | public class Test 33 | { 34 | public static string QueueName => "test"; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Tests/DMicroservices.RabbitMq.Test/ExampleConsumer2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using DMicroservices.RabbitMq.Base; 4 | using DMicroservices.RabbitMq.Consumer; 5 | using RabbitMQ.Client.Events; 6 | 7 | namespace DMicroservices.RabbitMq.Test 8 | { 9 | [ListenQueue("ExampleQueue2")] 10 | class ExampleConsumer2 : BasicConsumer 11 | { 12 | 13 | public override bool AutoAck => false; 14 | 15 | public override Action DataReceivedAction => DataReceived; 16 | 17 | private void DataReceived(ExampleModel model, BasicDeliverEventArgs e) 18 | { 19 | Console.WriteLine(model.Message); 20 | 21 | for (int i = 0; i < 10; i++) 22 | { 23 | Console.WriteLine(i); 24 | Thread.Sleep(300); 25 | } 26 | 27 | //Send Ack. 28 | BasicAck(e.DeliveryTag, false); 29 | 30 | } 31 | 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Tests/DMicroservices.RabbitMq.Test/ExampleModel.cs: -------------------------------------------------------------------------------- 1 | namespace DMicroservices.RabbitMq.Test 2 | { 3 | class ExampleModel 4 | { 5 | public string Message { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Tests/DMicroservices.RabbitMq.Test/ExchangeConsumer.cs: -------------------------------------------------------------------------------- 1 | using DMicroservices.RabbitMq.Consumer; 2 | using DMicroservices.RabbitMq.Model; 3 | using RabbitMQ.Client.Events; 4 | using RabbitMQ.Client; 5 | using System; 6 | using DMicroservices.RabbitMq.Base; 7 | 8 | namespace DMicroservices.RabbitMq.Test 9 | { 10 | [ListenQueue("ExampleQueue")] 11 | class ExchangeConsumer : BasicConsumer 12 | { 13 | 14 | public override ExchangeContent ExchangeContent => new ExchangeContent() { ExchangeName = "ExampleExchange", ExchangeType = ExchangeType.Fanout }; 15 | 16 | public override bool AutoAck => false; 17 | 18 | public override Action DataReceivedAction => DataReceived; 19 | 20 | private void DataReceived(ExampleModel model, BasicDeliverEventArgs e) 21 | { 22 | Console.WriteLine(model.Message); 23 | BasicAck(e.DeliveryTag, false); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Tests/DMicroservices.RabbitMq.Test/Program.cs: -------------------------------------------------------------------------------- 1 | using DMicroservices.RabbitMq.Base; 2 | using DMicroservices.RabbitMq.Model; 3 | using DMicroservices.RabbitMq.Producer; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Diagnostics; 7 | using System.Linq; 8 | using System.Threading; 9 | 10 | namespace DMicroservices.RabbitMq.Test 11 | { 12 | class Program 13 | { 14 | static void Main(string[] args) 15 | { 16 | ConsumerRegistry.Instance.Register(typeof(ExampleConsumer)); 17 | 18 | do 19 | { 20 | var x = Console.ReadLine(); 21 | RabbitMqPublisher.Instance.Publish("ExampleQueue", new ExampleModel() 22 | { 23 | Message = x 24 | }, 10); 25 | 26 | } while (true); 27 | 28 | 29 | Console.ReadLine(); 30 | //ThreadPool.QueueUserWorkItem(delegate 31 | //{ 32 | // while (true) 33 | // { 34 | // BasicPublishTest(); 35 | // Thread.Sleep(1); 36 | // } 37 | //}); 38 | 39 | //var consumerActiveSteps = new List(); 40 | //consumerActiveSteps.Add(new ConsumerActiveModel { ParallelismCount = 0, Type = typeof(ExampleConsumer) }); 41 | //consumerActiveSteps.Add(new ConsumerActiveModel { ParallelismCount = 0, Type = typeof(ExampleConsumer2) }); 42 | //var consumerActiveSteps2 = new List(); 43 | //consumerActiveSteps2.Add(new ConsumerActiveModel { ParallelismCount = 0, Type = typeof(ExampleConsumer) }); 44 | 45 | //while (true) 46 | //{ 47 | // string consoleInput = Console.ReadLine(); 48 | // switch (consoleInput) 49 | // { 50 | // case "e": 51 | // return; 52 | // case "ra": 53 | // ConsumerRegistry.Instance.RegisterWithList(consumerActiveSteps); 54 | // break; 55 | // case "i": 56 | // ConsumerRegistry.Instance.IncreaseParallelism(typeof(ExampleConsumer)); 57 | // break; 58 | // case "d": 59 | // ConsumerRegistry.Instance.DecreaseParallelism(typeof(ExampleConsumer)); 60 | // break; 61 | // case "i2": 62 | // ConsumerRegistry.Instance.IncreaseParallelism(typeof(ExampleConsumer2)); 63 | // break; 64 | // case "d2": 65 | // ConsumerRegistry.Instance.DecreaseParallelism(typeof(ExampleConsumer2)); 66 | // break; 67 | // case "un": 68 | // //ConsumerRegistry.Instance.UnRegisterWithList(regList); 69 | // ConsumerRegistry.Instance.UnRegisterWithList(consumerActiveSteps2, $"test_{0}"); 70 | // break; 71 | // case "cq": 72 | // ConsumerRegistry.Instance.ChangePrefetch(typeof(ExampleConsumer), 30); 73 | // break; 74 | // } 75 | 76 | //} 77 | 78 | //ExchangePublishTest(); 79 | } 80 | 81 | static void BasicPublishTest() 82 | { 83 | RabbitMqPublisher.Instance.Publish("ExampleQueue", new ExampleModel() 84 | { 85 | Message = "hello world." 86 | }); 87 | } 88 | 89 | static void ExchangePublishTest() 90 | { 91 | ConsumerRegistry.Instance.Register(typeof(ExchangeConsumer), 2); 92 | 93 | ThreadPool.QueueUserWorkItem(delegate 94 | { 95 | RabbitMqPublisher.Instance.PublishExchange("ExampleExchange", "", new ExampleModel() 96 | { 97 | Message = "hello world." 98 | }); 99 | }); 100 | 101 | Console.ReadLine(); 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /Tests/DMicroservices.RabbitMq.Test/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "DMicroservices.RabbitMq.Test": { 4 | "commandName": "Project", 5 | "environmentVariables": { 6 | "RABBITMQ_URI": "amqp://root:root@127.0.0.1:13034", 7 | "REDIS_URL": "localhost:13036" 8 | } 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /Tests/DMicroservices.RabbitMq.Test/TestConsumer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using DMicroservices.RabbitMq.Base; 5 | using DMicroservices.RabbitMq.Consumer; 6 | using RabbitMQ.Client.Events; 7 | 8 | namespace DMicroservices.RabbitMq.Test 9 | { 10 | [ListenQueue("Test")] 11 | class TestConsumer : BasicConsumer 12 | { 13 | public override bool AutoAck => false; 14 | public override Action DataReceivedAction => DataReceived; 15 | 16 | private void DataReceived(ExampleModel arg1, BasicDeliverEventArgs arg2) 17 | { 18 | 19 | } 20 | 21 | } 22 | } 23 | --------------------------------------------------------------------------------