├── .dockerignore
├── .gitignore
├── CODE_OF_CONDUCT.md
├── HandsOn.md
├── LICENSE
├── ManagedIdentity.md
├── README.md
├── SECURITY.md
├── SUPPORT.md
├── media
├── AddRoleAssignment.png
├── DBHelperBanner.png
├── UserAssignedManagedIdentity.png
├── UserAssignedManagedIdentity2.png
├── Worker Generate Constructor.png
├── add entity class.png
├── add reference changefeed.png
├── add reference.png
├── add todoservice class.png
├── azure-cosmos-db-create-new-account-detail.png
├── dotnet new console.png
├── dotnet new worker.png
├── generate constructor.png
├── nuget package manager.png
├── override OnChangeFeedDataSets.png
├── provision cosmosdb mongo.png
├── switch directory add package.png
├── switch directory add package2.png
└── worker project.png
└── src
├── Libraries
├── Microsoft.Solutions.CosmosDB.Mongo
│ ├── BusinessTransactionRepository.cs
│ ├── Microsoft.Solutions.CosmosDB.Mongo.csproj
│ └── MongoEntntyCollectionBase.cs
├── Microsoft.Solutions.CosmosDB.SQL.ChangeFeed
│ ├── ChangeFeedProcessorHelper.cs
│ ├── Microsoft.Solutions.CosmosDB.SQL.ChangeFeed.csproj
│ └── Watcher.cs
├── Microsoft.Solutions.CosmosDB.SQL
│ ├── BusinessTransactionRepository.cs
│ ├── Microsoft.Solutions.CosmosDB.SQL.csproj
│ └── SQLEntityCollectionBase.cs
├── Microsoft.Solutions.CosmosDB.Test
│ ├── CosmosDBTest.cs
│ └── Microsoft.Solutions.CosmosDB.Test.csproj
└── Microsoft.Solutions.CosmosDB
│ ├── CosmosDBEntityBase.cs
│ ├── GenericSpecification.cs
│ ├── IDataRepositoryProvider.cs
│ ├── IEntityModel.cs
│ ├── IRepository.cs
│ ├── ISpecification.cs
│ └── Microsoft.Solutions.CosmosDB.csproj
├── Microsoft CosmosDB Solution Accelerator.sln
├── Sample
├── Microsoft.Solutions.CosmosDB.Mongo.TODO.Service
│ ├── Microsoft.Solutions.CosmosDB.Mongo.TODO.Service.csproj
│ ├── Models
│ │ └── TODO.cs
│ └── TODOService.cs
├── Microsoft.Solutions.CosmosDB.Mongo.TODO.Tests
│ ├── Microsoft.Solutions.CosmosDB.Mongo.TODO.Tests.csproj
│ └── TODOServiceTests.cs
├── Microsoft.Solutions.CosmosDB.SQL.ChangeFeed.Service
│ ├── Dockerfile
│ ├── Microsoft.Solutions.CosmosDB.SQL.ChangeFeed.Service.csproj
│ ├── Models
│ │ └── TODO.cs
│ ├── Program.cs
│ ├── Properties
│ │ └── launchSettings.json
│ ├── Worker.cs
│ ├── appsettings.Development.json
│ └── appsettings.json
├── Microsoft.Solutions.CosmosDB.SQL.SDK.TODO.Service.Tests
│ ├── Microsoft.Solutions.CosmosDB.SQL.TODO.Service.Tests.csproj
│ └── TODOServiceTests.cs
├── Microsoft.Solutions.CosmosDB.SQL.SDK.TODO.Service
│ ├── Microsoft.Solutions.CosmosDB.SQL.TODO.Service.csproj
│ ├── Models
│ │ └── TODO.cs
│ └── TODOService.cs
└── Microsoft.Solutions.CosmosDB.WebHost
│ ├── Controllers
│ └── ToDoController.cs
│ ├── Dockerfile
│ ├── Microsoft.Solutions.CosmosDB.TODO.WebHost.csproj
│ ├── Program.cs
│ ├── Properties
│ └── launchSettings.json
│ ├── Startup.cs
│ ├── appsettings.Development.json
│ ├── appsettings.json
│ ├── azds.yaml
│ └── charts
│ └── microsoftsolutionscosmosdbwebhost
│ ├── .helmignore
│ ├── Chart.yaml
│ ├── templates
│ ├── NOTES.txt
│ ├── _helpers.tpl
│ ├── deployment.yaml
│ ├── ingress.yaml
│ ├── secrets.yaml
│ └── service.yaml
│ └── values.yaml
├── Utils
└── Microsoft.Solutions.HTTP
│ ├── HttpClient.cs
│ └── Microsoft.Solutions.HTTP.csproj
└── libraries
└── Microsoft.Solutions.CosmosDB.Security.ManagedIdentity
├── ConnectionStringAccessor.cs
└── Microsoft.Solutions.CosmosDB.Security.ManagedIdentity.csproj
/.dockerignore:
--------------------------------------------------------------------------------
1 | **/.classpath
2 | **/.dockerignore
3 | **/.env
4 | **/.git
5 | **/.gitignore
6 | **/.project
7 | **/.settings
8 | **/.toolstarget
9 | **/.vs
10 | **/.vscode
11 | **/*.*proj.user
12 | **/*.dbmdl
13 | **/*.jfm
14 | **/azds.yaml
15 | **/bin
16 | **/charts
17 | **/docker-compose*
18 | **/Dockerfile*
19 | **/node_modules
20 | **/npm-debug.log
21 | **/obj
22 | **/secrets.dev.yaml
23 | **/values.dev.yaml
24 | LICENSE
25 | README.md
--------------------------------------------------------------------------------
/.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 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Ww][Ii][Nn]32/
27 | [Aa][Rr][Mm]/
28 | [Aa][Rr][Mm]64/
29 | bld/
30 | [Bb]in/
31 | [Oo]bj/
32 | [Ll]og/
33 | [Ll]ogs/
34 |
35 | # Visual Studio 2015/2017 cache/options directory
36 | .vs/
37 | # Uncomment if you have tasks that create the project's static files in wwwroot
38 | #wwwroot/
39 |
40 | # Visual Studio 2017 auto generated files
41 | Generated\ Files/
42 |
43 | # MSTest test Results
44 | [Tt]est[Rr]esult*/
45 | [Bb]uild[Ll]og.*
46 |
47 | # NUnit
48 | *.VisualState.xml
49 | TestResult.xml
50 | nunit-*.xml
51 |
52 | # Build Results of an ATL Project
53 | [Dd]ebugPS/
54 | [Rr]eleasePS/
55 | dlldata.c
56 |
57 | # Benchmark Results
58 | BenchmarkDotNet.Artifacts/
59 |
60 | # .NET Core
61 | project.lock.json
62 | project.fragment.lock.json
63 | artifacts/
64 |
65 | # Tye
66 | .tye/
67 |
68 | # ASP.NET Scaffolding
69 | ScaffoldingReadMe.txt
70 |
71 | # StyleCop
72 | StyleCopReport.xml
73 |
74 | # Files built by Visual Studio
75 | *_i.c
76 | *_p.c
77 | *_h.h
78 | *.ilk
79 | *.meta
80 | *.obj
81 | *.iobj
82 | *.pch
83 | *.pdb
84 | *.ipdb
85 | *.pgc
86 | *.pgd
87 | *.rsp
88 | *.sbr
89 | *.tlb
90 | *.tli
91 | *.tlh
92 | *.tmp
93 | *.tmp_proj
94 | *_wpftmp.csproj
95 | *.log
96 | *.vspscc
97 | *.vssscc
98 | .builds
99 | *.pidb
100 | *.svclog
101 | *.scc
102 |
103 | # Chutzpah Test files
104 | _Chutzpah*
105 |
106 | # Visual C++ cache files
107 | ipch/
108 | *.aps
109 | *.ncb
110 | *.opendb
111 | *.opensdf
112 | *.sdf
113 | *.cachefile
114 | *.VC.db
115 | *.VC.VC.opendb
116 |
117 | # Visual Studio profiler
118 | *.psess
119 | *.vsp
120 | *.vspx
121 | *.sap
122 |
123 | # Visual Studio Trace Files
124 | *.e2e
125 |
126 | # TFS 2012 Local Workspace
127 | $tf/
128 |
129 | # Guidance Automation Toolkit
130 | *.gpState
131 |
132 | # ReSharper is a .NET coding add-in
133 | _ReSharper*/
134 | *.[Rr]e[Ss]harper
135 | *.DotSettings.user
136 |
137 | # TeamCity is a build add-in
138 | _TeamCity*
139 |
140 | # DotCover is a Code Coverage Tool
141 | *.dotCover
142 |
143 | # AxoCover is a Code Coverage Tool
144 | .axoCover/*
145 | !.axoCover/settings.json
146 |
147 | # Coverlet is a free, cross platform Code Coverage Tool
148 | coverage*.json
149 | coverage*.xml
150 | coverage*.info
151 |
152 | # Visual Studio code coverage results
153 | *.coverage
154 | *.coveragexml
155 |
156 | # NCrunch
157 | _NCrunch_*
158 | .*crunch*.local.xml
159 | nCrunchTemp_*
160 |
161 | # MightyMoose
162 | *.mm.*
163 | AutoTest.Net/
164 |
165 | # Web workbench (sass)
166 | .sass-cache/
167 |
168 | # Installshield output folder
169 | [Ee]xpress/
170 |
171 | # DocProject is a documentation generator add-in
172 | DocProject/buildhelp/
173 | DocProject/Help/*.HxT
174 | DocProject/Help/*.HxC
175 | DocProject/Help/*.hhc
176 | DocProject/Help/*.hhk
177 | DocProject/Help/*.hhp
178 | DocProject/Help/Html2
179 | DocProject/Help/html
180 |
181 | # Click-Once directory
182 | publish/
183 |
184 | # Publish Web Output
185 | *.[Pp]ublish.xml
186 | *.azurePubxml
187 | # Note: Comment the next line if you want to checkin your web deploy settings,
188 | # but database connection strings (with potential passwords) will be unencrypted
189 | *.pubxml
190 | *.publishproj
191 |
192 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
193 | # checkin your Azure Web App publish settings, but sensitive information contained
194 | # in these scripts will be unencrypted
195 | PublishScripts/
196 |
197 | # NuGet Packages
198 | *.nupkg
199 | # NuGet Symbol Packages
200 | *.snupkg
201 | # The packages folder can be ignored because of Package Restore
202 | **/[Pp]ackages/*
203 | # except build/, which is used as an MSBuild target.
204 | !**/[Pp]ackages/build/
205 | # Uncomment if necessary however generally it will be regenerated when needed
206 | #!**/[Pp]ackages/repositories.config
207 | # NuGet v3's project.json files produces more ignorable files
208 | *.nuget.props
209 | *.nuget.targets
210 |
211 | # Microsoft Azure Build Output
212 | csx/
213 | *.build.csdef
214 |
215 | # Microsoft Azure Emulator
216 | ecf/
217 | rcf/
218 |
219 | # Windows Store app package directories and files
220 | AppPackages/
221 | BundleArtifacts/
222 | Package.StoreAssociation.xml
223 | _pkginfo.txt
224 | *.appx
225 | *.appxbundle
226 | *.appxupload
227 |
228 | # Visual Studio cache files
229 | # files ending in .cache can be ignored
230 | *.[Cc]ache
231 | # but keep track of directories ending in .cache
232 | !?*.[Cc]ache/
233 |
234 | # Others
235 | ClientBin/
236 | ~$*
237 | *~
238 | *.dbmdl
239 | *.dbproj.schemaview
240 | *.jfm
241 | *.pfx
242 | *.publishsettings
243 | orleans.codegen.cs
244 |
245 | # Including strong name files can present a security risk
246 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
247 | #*.snk
248 |
249 | # Since there are multiple workflows, uncomment next line to ignore bower_components
250 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
251 | #bower_components/
252 |
253 | # RIA/Silverlight projects
254 | Generated_Code/
255 |
256 | # Backup & report files from converting an old project file
257 | # to a newer Visual Studio version. Backup files are not needed,
258 | # because we have git ;-)
259 | _UpgradeReport_Files/
260 | Backup*/
261 | UpgradeLog*.XML
262 | UpgradeLog*.htm
263 | ServiceFabricBackup/
264 | *.rptproj.bak
265 |
266 | # SQL Server files
267 | *.mdf
268 | *.ldf
269 | *.ndf
270 |
271 | # Business Intelligence projects
272 | *.rdl.data
273 | *.bim.layout
274 | *.bim_*.settings
275 | *.rptproj.rsuser
276 | *- [Bb]ackup.rdl
277 | *- [Bb]ackup ([0-9]).rdl
278 | *- [Bb]ackup ([0-9][0-9]).rdl
279 |
280 | # Microsoft Fakes
281 | FakesAssemblies/
282 |
283 | # GhostDoc plugin setting file
284 | *.GhostDoc.xml
285 |
286 | # Node.js Tools for Visual Studio
287 | .ntvs_analysis.dat
288 | node_modules/
289 |
290 | # Visual Studio 6 build log
291 | *.plg
292 |
293 | # Visual Studio 6 workspace options file
294 | *.opt
295 |
296 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
297 | *.vbw
298 |
299 | # Visual Studio LightSwitch build output
300 | **/*.HTMLClient/GeneratedArtifacts
301 | **/*.DesktopClient/GeneratedArtifacts
302 | **/*.DesktopClient/ModelManifest.xml
303 | **/*.Server/GeneratedArtifacts
304 | **/*.Server/ModelManifest.xml
305 | _Pvt_Extensions
306 |
307 | # Paket dependency manager
308 | .paket/paket.exe
309 | paket-files/
310 |
311 | # FAKE - F# Make
312 | .fake/
313 |
314 | # CodeRush personal settings
315 | .cr/personal
316 |
317 | # Python Tools for Visual Studio (PTVS)
318 | __pycache__/
319 | *.pyc
320 |
321 | # Cake - Uncomment if you are using it
322 | # tools/**
323 | # !tools/packages.config
324 |
325 | # Tabs Studio
326 | *.tss
327 |
328 | # Telerik's JustMock configuration file
329 | *.jmconfig
330 |
331 | # BizTalk build output
332 | *.btp.cs
333 | *.btm.cs
334 | *.odx.cs
335 | *.xsd.cs
336 |
337 | # OpenCover UI analysis results
338 | OpenCover/
339 |
340 | # Azure Stream Analytics local run output
341 | ASALocalRun/
342 |
343 | # MSBuild Binary and Structured Log
344 | *.binlog
345 |
346 | # NVidia Nsight GPU debugger configuration file
347 | *.nvuser
348 |
349 | # MFractors (Xamarin productivity tool) working folder
350 | .mfractor/
351 |
352 | # Local History for Visual Studio
353 | .localhistory/
354 |
355 | # BeatPulse healthcheck temp database
356 | healthchecksdb
357 |
358 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
359 | MigrationBackup/
360 |
361 | # Ionide (cross platform F# VS Code tools) working folder
362 | .ionide/
363 |
364 | # Fody - auto-generated XML schema
365 | FodyWeavers.xsd
366 |
367 | ##
368 | ## Visual studio for Mac
369 | ##
370 |
371 |
372 | # globs
373 | Makefile.in
374 | *.userprefs
375 | *.usertasks
376 | config.make
377 | config.status
378 | aclocal.m4
379 | install-sh
380 | autom4te.cache/
381 | *.tar.gz
382 | tarballs/
383 | test-results/
384 |
385 | # Mac bundle stuff
386 | *.dmg
387 | *.app
388 |
389 | # content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
390 | # General
391 | .DS_Store
392 | .AppleDouble
393 | .LSOverride
394 |
395 | # Icon must end with two \r
396 | Icon
397 |
398 |
399 | # Thumbnails
400 | ._*
401 |
402 | # Files that might appear in the root of a volume
403 | .DocumentRevisions-V100
404 | .fseventsd
405 | .Spotlight-V100
406 | .TemporaryItems
407 | .Trashes
408 | .VolumeIcon.icns
409 | .com.apple.timemachine.donotpresent
410 |
411 | # Directories potentially created on remote AFP share
412 | .AppleDB
413 | .AppleDesktop
414 | Network Trash Folder
415 | Temporary Items
416 | .apdisk
417 |
418 | # content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
419 | # Windows thumbnail cache files
420 | Thumbs.db
421 | ehthumbs.db
422 | ehthumbs_vista.db
423 |
424 | # Dump file
425 | *.stackdump
426 |
427 | # Folder config file
428 | [Dd]esktop.ini
429 |
430 | # Recycle Bin used on file shares
431 | $RECYCLE.BIN/
432 |
433 | # Windows Installer files
434 | *.cab
435 | *.msi
436 | *.msix
437 | *.msm
438 | *.msp
439 |
440 | # Windows shortcuts
441 | *.lnk
442 |
443 | # JetBrains Rider
444 | .idea/
445 | *.sln.iml
446 |
447 | ##
448 | ## Visual Studio Code
449 | ##
450 | .vscode/*
451 | !.vscode/settings.json
452 | !.vscode/tasks.json
453 | !.vscode/launch.json
454 | !.vscode/extensions.json
455 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Microsoft Open Source Code of Conduct
2 |
3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
4 |
5 | Resources:
6 |
7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns
10 |
--------------------------------------------------------------------------------
/HandsOn.md:
--------------------------------------------------------------------------------
1 | # How to use CosmosDB Helper Library
2 |
3 | >You need to have Azure subscription and provisioned Azure Cosmos DB (SQL API or MongoDB API).
4 | >
5 | >Let's start it with Azure Cosmos DB with SQL API first (You may easily shift it for Mongo API later)
6 |
7 |
8 |
9 | ## Work with SQL API (Azure Cosmos DB SDK)
10 |
11 | ### 0. Pre-requisites
12 |
13 | - We need to prepare Azure CosmosDB resource before starting it.
14 |
15 | I assume you have Azure CosmosDB SQL API instance and CosmosDB Mongo API instance both.
16 | If you don't have it, please prepare your CosmosDB resources. Here is the link [how to provision your Cosmos DB resources from Azure Portal](https://docs.microsoft.com/en-us/azure/cosmos-db/create-cosmosdb-resources-portal)
17 |
18 | Please make sure which API are you working with.
19 |
20 |
21 | - .NET Framework 5.0
22 |
23 | The Cosmos DB Helper libraries has been compiled with .NET Framework 5.0
24 | Before starting it, you need to install .NET Framework 5.0 in your development environment.
25 | If you don't have it, please install it from here - [.NET Framework 5.0 SDK Download](https://dotnet.microsoft.com/download/dotnet/thank-you/sdk-5.0.100-windows-x64-installer)
26 |
27 | If you tried to load the solution file with your Visual Studio 2019 without installing .NET Framework 5.0,
28 | You might get following error :
29 |
30 | >\Program Files\dotnet\sdk\3.1.201\Microsoft.Common.CurrentVersion.targets(1177,5): error MSB3644:
31 | >The reference assemblies for .NETFramework,Version=v5.0 were not found.
32 | >To resolve this, install the Developer Pack (SDK/Targeting Pack) for this framework version or retarget your application.
33 | >You can download .NET Framework Developer Packs at https://aka.ms/msbuild/developerpacks
34 |
35 | Unfortunately this link doesn't point .NET Framework version 5, only 4.8 now.
36 | To download version 5, you can download it from here [https://dotnet.microsoft.com/download/visual-studio-sdks](https://dotnet.microsoft.com/download/visual-studio-sdks)
37 | and I do recommend you upgrade your Visual Studio version up to 16.8.x.
38 |
39 |
40 | - VS Code
41 |
42 | It's OK to start with Visual Studio 2019 but I'm going to start with VS Code in this hands on.
43 | If you don't have it, you may download it from here - [Download VSCode](https://code.visualstudio.com/)
44 |
45 |
46 | ### 1. Create Project
47 | Please make sure all of pre-requisites are all set.
48 | Let's start hands on for now!
49 |
50 | Create Console project from Console Window
51 |
52 | ```
53 |
54 | dotnet new console -n CosmosHandsOn --framework net5.0
55 |
56 | ```
57 |
58 |
59 |
60 | After creating Console project name CosmosHandsOn, Switch the directory to newly created project.
61 |
62 | ```
63 |
64 | cd CosmosHandsOn
65 |
66 | ```
67 |
68 | ### 2. Add Reference CosmosDB Helper
69 | After switching the directory, add package Reference with Nuget installation
70 |
71 | ```
72 |
73 | dotnet add package EAE.Solutions.CosmosDB.SQL --version 0.7.3
74 |
75 | ```
76 |
77 |
78 |
79 | ### 3. Define Entity Class
80 | After referencing CosmosDB Helper, let's define Entity Class will be stored in CosmosDB
81 |
82 | Open your VS Code with this command
83 |
84 | ```
85 |
86 | code .
87 |
88 | ```
89 |
90 | then Add Entity Class with name **ToDo.cs**
91 |
92 |
93 |
94 | Define ToDo class with inheriting CosmosDBEntityBase in Microsoft.Solutions.CosmosDB Namespace.
95 | CosmosDBEntityBase class has responsibility for managing Entity's ID and PartitionKey which may effect to retrieving performance in the cosmos DB.
96 |
97 | ```csharp
98 |
99 | using System;
100 | using Microsoft.Solutions.CosmosDB;
101 | namespace CosmosHandsOn
102 | {
103 | public class ToDo : CosmosDBEntityBase
104 | {
105 | public string title { get; set; }
106 | public Status status { get; set; }
107 | public DateTime startDate { get; set; }
108 | public DateTime endDate { get; set; }
109 | public string notes { get; set; }
110 |
111 | private int _percentComplete;
112 |
113 | public int percentComplete
114 | {
115 | get { return _percentComplete; }
116 | set
117 | {
118 | if ((percentComplete < 0) || (percentComplete > 100))
119 | {
120 | throw new OverflowException("percent value should be between 0 to 100");
121 | }
122 | else
123 | {
124 | _percentComplete = percentComplete;
125 | }
126 | }
127 | }
128 | }
129 |
130 | public enum Status { New, InProcess, Done }
131 | }
132 |
133 | ```
134 |
135 | ### 4. Define Entity Collection Class
136 | Now add new EntityCollectionBase Class with name **ToDoService.cs**
137 |
138 | EntityCollectionBase class is managing Connection Objects and CRUD operations for CosmosDBEntityBase class objects
139 |
140 |
141 |
142 | Define ToDoService class with inheriting SQLEntityCollectionBase which is EntityCollectionBase class for SQL API and specify Entity Class types will manage.
143 |
144 | Once you inherit SQLEntityCollectionBase class, you should generate constructor which has 2 parameters for Database ConnectionString and Database Name.
145 |
146 | The 2 constructor parameters supposed to be passed to SQLEntityCollectionBase class for managing Azure CosmosDB connection and Entity object collection(container).
147 |
148 | ```csharp
149 |
150 | using System;
151 | using Microsoft.Solutions.CosmosDB.SQL;
152 |
153 | namespace CosmosHandsOn{
154 | public class ToDoService : SQLEntityCollectionBase
155 | {
156 | public ToDoService(string DataConnectionString, string CollectionName) : base(DataConnectionString, CollectionName)
157 | {
158 | }
159 | }
160 | }
161 |
162 | ```
163 |
164 |
165 |
166 | SQLEntityCollectionBase class provides features for Azure CosmosDB SQL API CRUD operations internally.
167 | Let's define CRUD operations in ToDoService.
168 |
169 | SQLEntityCollectionBase Class has EntityCollection property.
170 | You can operate(Crate, Replace, Update, Delete) Azure CosmosDB with your own Business Entities with it.
171 |
172 | Below is the CRUD operations you may easily interact with Azure CosmosDB
173 |
174 | - AddAsync method in EntityCollection can insert your object in CosmosDB
175 |
176 | ```csharp
177 |
178 | public async Task Create(ToDo todo)
179 | {
180 | return await this.EntityCollection.AddAsync(todo);
181 | }
182 |
183 | ```
184 |
185 | - SaveAsync method in EntityCollection can update your object in CosmosDB.
186 |
187 | ```csharp
188 |
189 | public async Task Update(ToDo todo)
190 | {
191 | return await this.EntityCollection.SaveAsync(todo);
192 | }
193 |
194 | ```
195 |
196 | - Get method in EntityCollection can retrieve Entity with Entity's id.(The Entity's identifier which will be managing by CosmosDB Helper class)
197 |
198 | ```csharp
199 |
200 | public async Task Find(string id)
201 | {
202 | return await this.EntityCollection.GetAsync(id);
203 | }
204 |
205 | ```
206 |
207 | - FindAllAsync method in EntityCollection can retrieve Entities with LINQ statements.
208 |
209 | ```csharp
210 |
211 | public async Task> Search(string notes)
212 | {
213 | return await this.EntityCollection.FindAllAsync(new GenericSpecification(x => x.notes.Contains(notes)));
214 | }
215 |
216 | ```
217 |
218 | - DeleteAsync method in EntityCollection can delete Entity by Entity's id or Entity itself.
219 |
220 | ```csharp
221 |
222 | public async Task Delete(string id)
223 | {
224 | await this.EntityCollection.DeleteAsync(id);
225 | }
226 |
227 | ```
228 |
229 | Done! You are ready to create, update, search and delete Entities with these simple methods.
230 |
231 | This is full ToDoServices.cs codes
232 |
233 | ```csharp
234 |
235 | using System;
236 | using System.Threading.Tasks;
237 | using System.Collections.Generic;
238 | using Microsoft.Solutions.CosmosDB;
239 | using Microsoft.Solutions.CosmosDB.SQL;
240 |
241 | namespace CosmosHandsOn{
242 | public class ToDoService : SQLEntityCollectionBase
243 | {
244 | public ToDoService(string DataConnectionString, string CollectionName) : base(DataConnectionString, CollectionName)
245 | {
246 | //just passing constructor parameters
247 | }
248 |
249 | public async Task Create(ToDo todo)
250 | {
251 | return await this.EntityCollection.AddAsync(todo);
252 | }
253 |
254 | public async Task Update(ToDo todo)
255 | {
256 | return await this.EntityCollection.SaveAsync(todo);
257 | }
258 |
259 | public async Task Find(string id)
260 | {
261 | return await this.EntityCollection.GetAsync(id);
262 | }
263 |
264 | public async Task> Search(string notes)
265 | {
266 | return await this.EntityCollection.FindAllAsync(new GenericSpecification(x => x.notes.Contains(notes)));
267 | }
268 |
269 | public async Task Delete(string id)
270 | {
271 | await this.EntityCollection.DeleteAsync(id);
272 | }
273 | }
274 | }
275 |
276 | ```
277 |
278 | Now you may put this ToDoService on wherever you want to host it through MicroService containers or Azure Functions.
279 |
280 | Let's try to test it with Console Application from here.
281 |
282 | Open **Programs.cs** and define CosmosDB ConnectionString.
283 | To invoking asynchronous methods we need to change **static void Main** method signature to **async static Task Main** .
284 |
285 | Please check your Azure CosmosDB connection string from Azure portal and copy & paste it like below.
286 |
287 | ```csharp
288 |
289 | using System;
290 | using System.Threading.Tasks;
291 |
292 | namespace CosmosHandsOn
293 | {
294 | class Program
295 | {
296 | static string connectionString = "{Put your connectionstring}";
297 |
298 | async static Task Main(string[] args)
299 | {
300 | }
301 | }
302 | }
303 |
304 | ```
305 |
306 | And instantiate ToDoService with connection string and Database name together.
307 | The SQLEntityCollectionBase which has been inherited by ToDoService is going to check existence of Database and once it is not exiting, it will generate Database automatically on the fly.
308 |
309 | Put this code for instancing ToDoService like below
310 |
311 | ```csharp
312 |
313 | async static Task Main(string[] args)
314 | {
315 | var todoService = new ToDoService(connectionString, "CosmosHandson");
316 | }
317 |
318 | ```
319 |
320 | It will create CosmosHandson Database in your Azure CosmosDB.
321 | Now add the codes for testing ToDoService with this codes
322 |
323 | Create ToDo object like below.
324 |
325 | ```csharp
326 |
327 |
328 | var todo = new ToDo()
329 | {
330 | title = "This is test ToDo",
331 | startDate = DateTime.Now,
332 | endDate = DateTime.Now.AddDays(2),
333 | percentComplete = 0,
334 | notes = "Cosmos DB is really cool!",
335 | status = Status.New
336 | };
337 |
338 | ```
339 |
340 | You might be acknowledged that ToDo class has id and __partitionkey properties natively.
341 | You don't necessary to touch them from your code. the id and _partitionkey will be managed by CosmosDB Helper by itself.
342 |
343 | After instancing ToDo class let's add the codes following.
344 |
345 | ```csharp
346 |
347 | using System;
348 | using System.Threading.Tasks;
349 |
350 | namespace CosmosHandsOn
351 | {
352 | class Program
353 | {
354 | static string connectionString = "{Put your connectionstring}";
355 |
356 | async static Task Main(string[] args)
357 | {
358 | var todoService = new ToDoService(connectionString, "CosmosHandson");
359 |
360 | var todo = new ToDo()
361 | {
362 | title = "This is test ToDo",
363 | startDate = DateTime.Now,
364 | endDate = DateTime.Now.AddDays(2),
365 | percentComplete = 0,
366 | notes = "Cosmos DB is really cool!",
367 | status = Status.New
368 | };
369 |
370 | //Insert ToDO
371 | var objTodo1 = await todoService.Create(todo);
372 |
373 | //Update ToDo
374 | objTodo1.title = "Updating test ToDo";
375 | await todoService.Update(objTodo1);
376 |
377 | //Search ToDo
378 | var objRetrived = await todoService.Find(objTodo1.id);
379 | Console.WriteLine($"Found object! it's title is {objRetrived.title}");
380 |
381 | //Find ToDos
382 | var todos = await todoService.Search("Cosmos");
383 | foreach (var item in todos)
384 | {
385 | Console.WriteLine($"{item.id} - {item.title} - {item.notes} - {item.status}");
386 | }
387 |
388 | //Delete ToDos
389 | await todoService.Delete(objTodo1.id);
390 | Console.WriteLine($"The Todo object which has title - {objTodo1.title} has been removed");
391 | }
392 | }
393 | }
394 |
395 | ```
396 |
397 | and Execute the code with pressing F5(Debugging) or CTRL + F5(Execute without Debugging)
398 | You may check every CRUD operations are working perfectly.
399 |
400 |
401 |
402 | It's time to use Azure CosmosDB Mongo API Service with our code.
403 |
404 |
405 |
406 | ---
407 |
408 |
409 | ## Work with Cosmos DB for Mongo API
410 | >It's easy! We've already implemented all CRUD operations in ToDoService class.
411 | Azure Cosmos DBHelper provides exactly same development experience with previous one what we did.
412 | >
413 | >To start with Azure CosmosDB for Mongo API, You need to prepare Azure CosmosDB for Mongo API instance.
414 | If You don't have it yet, deploy Azure CosmosDB for MongoDB like blow before moving further.
415 | >
416 | >
417 | >
418 | >After provisioning Azure CosmosDB for Mongo API, grep the connection string.
419 | >The Connection string format for Mongo is different with Azure CosmosDB for SQL API.
420 |
421 | ### 1. Add Reference
422 |
423 | Try to Add Azure CosmosDB mongo Helper library with nuget package reference in your source directory like below
424 |
425 | ```
426 |
427 | dotnet add package EAE.Solutions.CosmosDB.Mongo --version 0.7.3
428 |
429 | ```
430 |
431 |
432 |
433 |
434 | ### 2. Inherit MongoEntityCollectionBase in ToDoService
435 | Open the VS Code again from the source folder.
436 |
437 | ```
438 |
439 | code .
440 |
441 | ```
442 |
443 | In previous code, ToDoService inherited SQLEntityCollectionBase.
444 | Just replace ToDoService's base class with **MongoEntityCollectionBase** and replace **using Microsoft.Solutions.CosmosDB.SQL** namespace to **Microsoft.Solutions.CosmosDB.Mongo**.
445 |
446 | ```csharp
447 | using System;
448 | using Microsoft.Solutions.CosmosDB.Mongo;
449 | using System.Threading.Tasks;
450 | using System.Collections.Generic;
451 | using Microsoft.Solutions.CosmosDB;
452 |
453 | namespace CosmosHandsOn{
454 | public class ToDoService : MongoEntntyCollectionBase
455 | {
456 | public ToDoService(string DataConnectionString, string CollectionName) : base(DataConnectionString, CollectionName)
457 | {
458 | }
459 |
460 | public async Task Create(ToDo todo)
461 | {
462 | return await this.EntityCollection.AddAsync(todo);
463 | }
464 |
465 | public async Task Update(ToDo todo)
466 | {
467 | return await this.EntityCollection.SaveAsync(todo);
468 | }
469 |
470 | public async Task Find(string id)
471 | {
472 | return await this.EntityCollection.GetAsync(id);
473 | }
474 |
475 | public async Task> Search(string notes)
476 | {
477 | return await this.EntityCollection.FindAllAsync(new GenericSpecification(x => x.notes.Contains(notes)));
478 | }
479 |
480 | public async Task Delete(string id)
481 | {
482 | await this.EntityCollection.DeleteAsync(id);
483 | }
484 |
485 | }
486 | }
487 | ```
488 |
489 | ### 3. Update ConnectionString
490 | > Don't forget to update your connection string for MongoDB in programs.cs file!
491 |
492 | That's all we should do to switch our code for using CosmosDB Mongo API.
493 | Just Execute the code with pressing F5(Debugging) or CTRL + F5(Execute without Debugging)
494 |
495 |
496 | ## Dependency Injection in ASP.net
497 |
498 | All of CosmosDB Helper is sharing [IDataRepositoryProvider](./src/Libraries/Microsoft.CosmosDB/../Microsoft.Solutions.CosmosDB/IDataRepositoryProvider.cs) interface.
499 |
500 | ```csharp
501 |
502 | namespace Microsoft.Solutions.CosmosDB
503 | {
504 | public interface IDataRepositoryProvider
505 | {
506 | IRepository EntityCollection { get; init ; }
507 | }
508 | }
509 |
510 | ```
511 |
512 | so you may inject your dependency with this interface.
513 |
514 | This is the sample code snippet for showing how to inject dependency into DoToService.
515 |
516 | ```csharp
517 |
518 | services.AddTransient, TODOService>(x => { return new TODOService(configuration["ConnectionString"], "CosmosHandson"); });
519 |
520 | ```
521 |
522 | You may check the ToDo ASP.net API sample project from [here](../../tree/main/src/Sample/Microsoft.Solutions.CosmosDB.WebHost)
523 |
524 | ## Working in Visual Studio 2019 or 2017
525 | Absolutely Visual Studio is the first citizen .NET Development.
526 | If you want to start hands on from .NET Framework, you may reference proper package with Nuget Package manager.
527 |
528 |
529 |
530 |
531 | ## EAE.Solutions.CosmosDB.SQL.ChangeFeed - Change feed Processor Helper
532 | > Currently it supports **SQL Core API only**, EAE.Solutions.CosmosDB.MongoDB.ChangeFeed will be released next version.
533 |
534 |
535 | The change feed processor is part of the Azure Cosmos DB SDK V3.
536 | **Watcher** class in Microsoft.Solutions.CosmosDB.SQL.ChangeFeed namespace derived from BackgroundService, which supports hosting and managing Change feed processors as well as handle change entity collections.
537 |
538 | Just Passing monitored entity collections(container) name as parameter to Watcher class then you can catch the changed entity sets.
539 |
540 | We can host Watcher on .NET Generic Host in ASP.net core - https://docs.microsoft.com/en-us/dotnet/architecture/microservices/multi-container-microservice-net-applications/background-tasks-with-ihostedservice
541 |
542 | See the Sample Application for Azure CosmosDB Change feed host [here](./Sample/Microsoft.Solutions.CosmosDB.SQL.ChangeFeed.Service)
543 |
544 | ```csharp
545 |
546 | using Microsoft.Extensions.Configuration;
547 | using Microsoft.Solutions.CosmosDB.SQL.ChangeFeed;
548 | using Microsoft.Solutions.CosmosDB.SQL.ChangeFeed.Service.Models;
549 | using Newtonsoft.Json;
550 | using System;
551 | using System.Collections.Generic;
552 | using System.Threading;
553 | using System.Threading.Tasks;
554 |
555 | namespace Microsoft.Solutions.CosmosDB.SQL.TODO.ChangeFeed.Service
556 | {
557 | public class Worker : Watcher
558 | {
559 | ///
560 | /// Passing configuration by ASPnet core Dependency Injection
561 | /// This Application sample shows how to detact changes for TODO collection by Microsoft.Solutions.CosmosDB.SQL.TODO.WebHost Demo App
562 | ///
563 | /// Check appsettings.json file definition
564 | public Worker(IConfiguration configuration) : base(configuration["Values:DBConnectionString"],
565 | configuration["Values:MonitoredDatabaseName"],
566 | configuration["Values:MonitoredContainerName"])
567 | {
568 | }
569 |
570 | protected override Task OnChangedFeedDataSets(IReadOnlyCollection changes, CancellationToken cancellationToken)
571 | {
572 | //put your business logics with changes
573 | foreach (var item in changes)
574 | {
575 | Console.WriteLine($"Detected operation for item with id {item.id} => {JsonConvert.SerializeObject(item)}");
576 | }
577 |
578 | return base.OnChangedFeedDataSets(changes, cancellationToken);
579 | }
580 | }
581 | }
582 |
583 |
584 | ```
585 |
586 | Now, Let's make our hands dirt by creating Change Feed Process Host for DoTo Entity Container what we tested in previous handson with Watcher class.
587 |
588 | ### 1. Create Project
589 | Create Worker Service project from Console Window.
590 | dotnet CLI tool provides [Worker Service host project template](https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-new-sdk-templates#web-others).
591 |
592 | Type dotnet CLI command like below in your Console.
593 |
594 | ```
595 |
596 | dotnet new worker -n CosmosHandsOnChangeFeed --framework net5.0
597 |
598 | ```
599 |
600 |
601 |
602 | After creating project template, move the directory path to CosmosHandsOnChangeFeed
603 |
604 | ```
605 | cd .\CosmosHandsOnChangeFeed
606 |
607 | ```
608 | ### 2. Add Reference CosmosDB Helper
609 | After switching the directory, add package Reference with Nuget installation.
610 | This Nuget package contains Watcher class in Microsoft.Solutions.CosmosDB.SQL.ChangeFeed Namespace
611 |
612 | ```
613 |
614 | dotnet add package EAE.Solutions.CosmosDB.SQL.ChangeFeed --version 0.7.3
615 |
616 | ```
617 |
618 |
619 |
620 | Then Open VSCode
621 |
622 | ```
623 |
624 | code .
625 |
626 | ```
627 |
628 | You may check the .NET Generic Host ASP.net core project scarffolding source files.
629 |
630 |
631 |
632 | ### 3. Add ToDo Entity class
633 | Now we are going to add Entity Class where Monitored Container has.
634 | We are going to watch ToDos Container what we created in previous handson.
635 |
636 | Add new file with ToDo.cs and Copy below code and paste to ToDo.cs file
637 |
638 | ```csharp
639 |
640 | using System;
641 | using Microsoft.Solutions.CosmosDB;
642 | namespace CosmosHandsOnChangeFeed
643 | {
644 | public class ToDo : CosmosDBEntityBase
645 | {
646 | public string title { get; set; }
647 | public Status status { get; set; }
648 | public DateTime startDate { get; set; }
649 | public DateTime endDate { get; set; }
650 | public string notes { get; set; }
651 |
652 | private int _percentComplete;
653 |
654 | public int percentComplete
655 | {
656 | get { return _percentComplete; }
657 | set
658 | {
659 | if ((percentComplete < 0) || (percentComplete > 100))
660 | {
661 | throw new OverflowException("percent value should be between 0 to 100");
662 | }
663 | else
664 | {
665 | _percentComplete = percentComplete;
666 | }
667 | }
668 | }
669 | }
670 |
671 | public enum Status { New, InProcess, Done }
672 | }
673 |
674 | ```
675 | ### 4. Inherit Watcher Class in EAE.Solutions.CosmosDB.SQL.ChangeFeed
676 |
677 | We have prepared ToDo EntityClass for monitoring entity container.
678 | Now let's set up Watcher class to minitoring ToDos container.
679 |
680 | Open Worker.cs file
681 |
682 | ``` csharp
683 | using System;
684 | using System.Collections.Generic;
685 | using System.Linq;
686 | using System.Threading;
687 | using System.Threading.Tasks;
688 | using Microsoft.Extensions.Hosting;
689 | using Microsoft.Extensions.Logging;
690 |
691 | namespace CosmosHandsOnChangeFeed
692 | {
693 | public class Worker : BackgroundService
694 | {
695 | private readonly ILogger _logger;
696 |
697 | public Worker(ILogger logger)
698 | {
699 | _logger = logger;
700 | }
701 |
702 | protected override async Task ExecuteAsync(CancellationToken stoppingToken)
703 | {
704 | while (!stoppingToken.IsCancellationRequested)
705 | {
706 | _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
707 | await Task.Delay(1000, stoppingToken);
708 | }
709 | }
710 | }
711 | }
712 | ```
713 |
714 | There are some sample codes for BackgroundService.
715 | Add ```Microsoft.Solutions.CosmosDB.SQL.ChangeFeed``` Namespace and then change its Base Class from ```BackgroundService``` to ```Watcher```.
716 | Then remove whole codes in Worker class like below.
717 |
718 | ```csharp
719 |
720 | using System;
721 | using System.Collections.Generic;
722 | using System.Linq;
723 | using System.Threading;
724 | using System.Threading.Tasks;
725 | using Microsoft.Extensions.Hosting;
726 | using Microsoft.Extensions.Logging;
727 | using Microsoft.Solutions.CosmosDB.SQL.ChangeFeed;
728 |
729 | namespace CosmosHandsOnChangeFeed
730 | {
731 | public class Worker : Watcher
732 | {
733 |
734 |
735 | }
736 | }
737 |
738 | ```
739 |
740 | Now Add Constructor with IConfiguration Dependency Injection and Pass 3 parameter to its Base class like below.
741 |
742 | the 3 parameters supposed to be passed to Base class is Azure CosmosDB Connectionstring and Monitored Database and Container name.
743 | We are going to update parameter information in appsettings.json file.
744 |
745 | ASPnet core has its native Dependency Injection framework and it will read appsettings.json file then pass to every hosted instances at its constructor.
746 |
747 | ```csharp
748 |
749 | public class Worker : Watcher
750 | {
751 | public Worker(IConfiguration configuration ) : base(configuration["Values:DBConnectionString"],
752 | configuration["Values:MonitoredDatabaseName"],
753 | configuration["Values:MonitoredContainerName"])
754 | {
755 | }
756 | }
757 |
758 | ```
759 | ### 5. Override OnChangeFeedDataSets
760 |
761 | Now Override ```OnChangeFeedDataSets``` from its Base class like below
762 |
763 |
764 |
765 | ```csharp
766 |
767 | protected override Task OnChangedFeedDataSets(IReadOnlyCollection changes, CancellationToken cancellationToken)
768 | {
769 | return base.OnChangedFeedDataSets(changes, cancellationToken);
770 | }
771 |
772 | ```
773 |
774 | Whenever Monitored Entity Container updated, The Watcher will catch them with ``IReadOnlyCollection`` changes parameter.
775 |
776 | Just add the code for Printing out changes into Console window like below:
777 |
778 | ```csharp
779 | protected override Task OnChangedFeedDataSets(IReadOnlyCollection changes, CancellationToken cancellationToken)
780 | {
781 | foreach (var item in changes)
782 | {
783 | Console.WriteLine($"Changed ToDo => Title : {item.title} /n Status : {item.status} / Notes : {item.notes} ");
784 | }
785 |
786 | return base.OnChangedFeedDataSets(changes, cancellationToken);
787 | }
788 | ```
789 |
790 | You can add your own business logics in here instead of Console print out at your requirements.
791 |
792 | Here is the whole Worker.cs codes :
793 |
794 | ```csharp
795 | using System;
796 | using System.Collections.Generic;
797 | using System.Threading;
798 | using System.Threading.Tasks;
799 | using Microsoft.Extensions.Configuration;
800 | using Microsoft.Solutions.CosmosDB.SQL.ChangeFeed;
801 |
802 | namespace CosmosHandsOnChangeFeed
803 | {
804 | public class Worker : Watcher
805 | {
806 | public Worker(IConfiguration configuration ) : base(configuration["Values:DBConnectionString"],
807 | configuration["Values:MonitoredDatabaseName"],
808 | configuration["Values:MonitoredContainerName"])
809 | {
810 | }
811 |
812 | protected override Task OnChangedFeedDataSets(IReadOnlyCollection changes, CancellationToken cancellationToken)
813 | {
814 | foreach (var item in changes)
815 | {
816 | Console.WriteLine($"Changed ToDo => Title : {item.title} /n Status : {item.status} / Notes : {item.notes} ");
817 | }
818 |
819 | return base.OnChangedFeedDataSets(changes, cancellationToken);
820 | }
821 |
822 | }
823 | }
824 | ```
825 |
826 |
827 | ### 6. Update Configuration for ConnectionString and Monitored Entity Container Information
828 | Open appsettings.json file and add configuration information like below :
829 |
830 | ```json
831 | {
832 | "Logging": {
833 | "LogLevel": {
834 | "Default": "Information",
835 | "Microsoft": "Warning",
836 | "Microsoft.Hosting.Lifetime": "Information"
837 | }
838 | },
839 | "Values" : {
840 | "DBConnectionString" : "{Put Your Connectionstring}",
841 | "MonitoredDatabaseName" : "CosmosHandson",
842 | "MonitoredContainerName" : "ToDos"
843 | }
844 | }
845 | ```
846 |
847 | Now you are all set.
848 | Whenerver ToDos entity container has been changed, you can catch them with this Worker class.
849 | You may put it on Container and scale with Kubernetes clusters.
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) Microsoft Corporation.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE
22 |
--------------------------------------------------------------------------------
/ManagedIdentity.md:
--------------------------------------------------------------------------------
1 | # EAE.Solutions.CosmosDB.Security.ManagedIdentity
2 | [EAE.Solutions.CosmosDB.Security.ManagedIdentity](src/libraries/Microsoft.Solutions.CosmosDB.Security.ManagedIdentity/) helps retrieve Azure Cosmos DB Connection Strings with Managed Identity Information.
3 |
4 | It may elimiate the security concerns of managing credentials/secrets and only can access Azure Cosmos DB from developer's dev environment or designated Azure subscription.
5 |
6 | Using Managed Identity you can control any Azure resources with predefined (or custom defined) RBACs.
7 |
8 | If you need to get more information about Azure Managed Identity, Please check this URL - https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview
9 |
10 | ## How to use EAE.Solutions.CosmosDB.Security.ManagedIdentity
11 |
12 | ### 1. Create User define Managed Identity
13 | Create User Assigned Managed Identity in your resource group
14 | 
15 |
16 | Fill up information where it being deployed
17 | 
18 |
19 | After deploying User Assigned Managed Identity, Let's assign the predefined roles for Azure Cosmos DB
20 |
21 | ### 2. Add Role Assignment
22 | Select Azure role assignments in Managed Identity that you created then select **Add role assignment** on top then assign its role like below :
23 | **DocumentDB Account Contributor** can retrive Read/Write Connection String Information within designated resource group.
24 |
25 | 
26 |
27 | ### 3. Get Subscription ID, Resource Group Name and Client ID
28 | Go to **Overview** menu in your Managed Identity and grap the three information - **Subscription ID**, **Regource group Name** and **Client ID**
29 |
30 | ### 4. Get Azure Cosmos DB Connection String
31 | Install **EAE.Solutions.CosmosDB.Security.ManagedIdentity** Package in your Visual Studio or Visual Studio Code from Nuget :
32 |
33 | ```
34 | dotnet add package EAE.Solutions.CosmosDB.Security.ManagedIdentity --version 0.7.3
35 | ```
36 |
37 | Get Azure Cosmos DB Connection String like below :
38 |
39 | ``` csharp
40 | //Should install Package from Nuget (EAE.Solutions.CosmosDB.Security.ManagedIdentity)
41 | using Microsoft.Solutions.CosmosDB.Security.ManagedIdentity;
42 |
43 | //SubscriptionID, ResourceGroup Name, Cosmos DB Account Name and Managed Identity ClientID is required
44 | public async Task GetConnectionInfo(string SubscriptionId,
45 | string ResourceGroupName,
46 | string CosmosAccountName,
47 | string ManagedIdentityClientID)
48 | {
49 | return await ConnectionStringAccessor
50 | .Create(SubscriptionId, ResourceGroupName, CosmosAccountName)
51 | .GetConnectionStringsAsync(ManagedIdentityClientID);
52 | }
53 |
54 |
55 | ```
56 | The **CosmosConnectionStrings** class contains 4 connection strings - Primary/Secondary Read,Write ConnectionStrings and Primary/Seconday ReadOnly Connection strings. You may choose one of them at your preference.
57 |
58 | ```csharp
59 | public class CosmosConnectionStrings
60 | {
61 | public string PrimaryReadWriteKey { get; set; }
62 | public string SecondaryReadWriteKey { get; set; }
63 | public string PrimaryReadOnlyKey { get; set; }
64 | public string SecondaryReadOnlyKey { get; set; }
65 | }
66 | ```
67 |
68 | You may check the [Sample Application code](src/Sample/Microsoft.Solutions.CosmosDB.WebHost/Startup.cs) for it from here - [Web Host Sample](src/Sample/Microsoft.Solutions.CosmosDB.WebHost)
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 | ## About this repository
3 | Welcome to Azure CosmosDB Solution Accelerator (Azure CosmosDB Helper).
4 |
5 | Azure CosmosDB Helper supports MongoDB API and SQL Core API interface with LINQ statements.
6 | It abstracts how data can be persisted and retrived from Database by implmenting Repository Pattern.
7 | In Architecture perspective, it decouples the data access layer from business layer so developers can their Business Entities CRUD Operations through much streightforward way without learning specific query languages for each APIs.
8 |
9 | Once your business logic has been built with LINQ statements with Azure CosmosDB Helper, you may easily switch two APIs (SQL and Mongo) with very few code changes.
10 |
11 | ## Version History
12 | - ### v 0.7.3 Update
13 | - #### Access Azure CosmosDB with [Managed Identity](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview)
14 | - [**EAE.Solutions.CosmosDB.Security.ManagedIdentity**](ManagedIdentity.md) has been released
15 | - Get rid of secrets from your configuration or source code
16 | - Retireve Azure Cosmos DB Connection Strings with Managed Identity (**DocumentDB Account Contributor Role**)
17 | - Persistent Azure resource access with single Managed Identity
18 |
19 | - ### v 0.7 Update
20 | - #### Change feed processor for Azure CosmosDB Core SQL API
21 | - **Microsoft.Solutions.CosmosDB.SQL.ChangeFeed** (ChangeFeed Processor Helper) has been released
22 | - Automatic lease container creation
23 | - Multiple process host support for parallel execution in Microservice deployment
24 | - Delegate process template for detecting ChangeSets.
25 |
26 |
27 | - #### Improved performance with optimized Connection Object
28 |
29 | - #### CosmosEntityBase Name has been changed to **CosmosDBEntityBase**
30 | - Azure CosmosDB Core SQL API EF Core Deprecated
31 | - Azure CosmosDB Provider - EF Core wrapper has been deprecated
32 | (EF Core Framework's performance issue)
33 |
34 | - ### v 0.6 First Release
35 | - #### Azure CosmosDB Core SQL API support
36 | - Azure CosmosDB SDK wrapper
37 | - Azure CosmosDB Provider - EF Core wrapper
38 | - #### Azure CosmosDB MongoDB SQL API Support
39 | - MongoDB.Driver wrapper
40 |
41 | ## Prerequisites
42 | This source code has been built with .NET framework 5.0
43 | (but you may build it with .NET Core 3.1 as well)
44 |
45 | ## Purpose
46 | CosmosDB Solution Accelerator helps developers who wants to use CosmosDB with **SIMPLE** and **DEVELOPMENT CONSISTENCY**.
47 | Developers can easily switch CosmosDB APIs between SQL API and Mongo API with little changes
48 |
49 | ## How to Work with it
50 | You may start with [HandsOn](./HandsOn.md) page.
51 | All of libraries can be referenced though [Nuget packages](https://www.nuget.org/packages?q=EAE.Solutions) to your project.
52 |
53 | ## License
54 | Copyright (c) Microsoft Corporation
55 |
56 | All rights reserved.
57 |
58 | MIT License
59 |
60 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
61 |
62 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
63 |
64 | THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
65 |
66 | ## Contributing
67 |
68 | This project welcomes contributions and suggestions. Most contributions require you to agree to a
69 | Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
70 | the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
71 |
72 | When you submit a pull request, a CLA bot will automatically determine whether you need to provide
73 | a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions
74 | provided by the bot. You will only need to do this once across all repos using our CLA.
75 |
76 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
77 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
78 | contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
79 |
80 | ## Trademarks
81 |
82 | This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft
83 | trademarks or logos is subject to and must follow
84 | [Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general).
85 | Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship.
86 | Any use of third-party trademarks or logos are subject to those third-party's policies.
87 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## Security
4 |
5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
6 |
7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)), please report it to us as described below.
8 |
9 | ## Reporting Security Issues
10 |
11 | **Please do not report security vulnerabilities through public GitHub issues.**
12 |
13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report).
14 |
15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc).
16 |
17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc).
18 |
19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
20 |
21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
22 | * Full paths of source file(s) related to the manifestation of the issue
23 | * The location of the affected source code (tag/branch/commit or direct URL)
24 | * Any special configuration required to reproduce the issue
25 | * Step-by-step instructions to reproduce the issue
26 | * Proof-of-concept or exploit code (if possible)
27 | * Impact of the issue, including how an attacker might exploit the issue
28 |
29 | This information will help us triage your report more quickly.
30 |
31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs.
32 |
33 | ## Preferred Languages
34 |
35 | We prefer all communications to be in English.
36 |
37 | ## Policy
38 |
39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd).
40 |
41 |
--------------------------------------------------------------------------------
/SUPPORT.md:
--------------------------------------------------------------------------------
1 | # TODO: The maintainer of this repo has not yet edited this file
2 |
3 | **REPO OWNER**: Do you want Customer Service & Support (CSS) support for this product/project?
4 |
5 | - **No CSS support:** Fill out this template with information about how to file issues and get help.
6 | - **Yes CSS support:** Fill out an intake form at [aka.ms/spot](https://aka.ms/spot). CSS will work with/help you to determine next steps. More details also available at [aka.ms/onboardsupport](https://aka.ms/onboardsupport).
7 | - **Not sure?** Fill out a SPOT intake as though the answer were "Yes". CSS will help you decide.
8 |
9 | *Then remove this first heading from this SUPPORT.MD file before publishing your repo.*
10 |
11 | # Support
12 |
13 | ## How to file issues and get help
14 |
15 | This project uses GitHub Issues to track bugs and feature requests. Please search the existing
16 | issues before filing new issues to avoid duplicates. For new issues, file your bug or
17 | feature request as a new Issue.
18 |
19 | For help and questions about using this project, please **REPO MAINTAINER: INSERT INSTRUCTIONS HERE
20 | FOR HOW TO ENGAGE REPO OWNERS OR COMMUNITY FOR HELP. COULD BE A STACK OVERFLOW TAG OR OTHER
21 | CHANNEL. WHERE WILL YOU HELP PEOPLE?**.
22 |
23 | ## Microsoft Support Policy
24 |
25 | Support for this **PROJECT or PRODUCT** is limited to the resources listed above.
26 |
--------------------------------------------------------------------------------
/media/AddRoleAssignment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/CosmosDB-Solution-Accelerator-CosmosDB-Helper/9242e5f80141e6f33800cc73ee3b4f56143af76a/media/AddRoleAssignment.png
--------------------------------------------------------------------------------
/media/DBHelperBanner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/CosmosDB-Solution-Accelerator-CosmosDB-Helper/9242e5f80141e6f33800cc73ee3b4f56143af76a/media/DBHelperBanner.png
--------------------------------------------------------------------------------
/media/UserAssignedManagedIdentity.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/CosmosDB-Solution-Accelerator-CosmosDB-Helper/9242e5f80141e6f33800cc73ee3b4f56143af76a/media/UserAssignedManagedIdentity.png
--------------------------------------------------------------------------------
/media/UserAssignedManagedIdentity2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/CosmosDB-Solution-Accelerator-CosmosDB-Helper/9242e5f80141e6f33800cc73ee3b4f56143af76a/media/UserAssignedManagedIdentity2.png
--------------------------------------------------------------------------------
/media/Worker Generate Constructor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/CosmosDB-Solution-Accelerator-CosmosDB-Helper/9242e5f80141e6f33800cc73ee3b4f56143af76a/media/Worker Generate Constructor.png
--------------------------------------------------------------------------------
/media/add entity class.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/CosmosDB-Solution-Accelerator-CosmosDB-Helper/9242e5f80141e6f33800cc73ee3b4f56143af76a/media/add entity class.png
--------------------------------------------------------------------------------
/media/add reference changefeed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/CosmosDB-Solution-Accelerator-CosmosDB-Helper/9242e5f80141e6f33800cc73ee3b4f56143af76a/media/add reference changefeed.png
--------------------------------------------------------------------------------
/media/add reference.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/CosmosDB-Solution-Accelerator-CosmosDB-Helper/9242e5f80141e6f33800cc73ee3b4f56143af76a/media/add reference.png
--------------------------------------------------------------------------------
/media/add todoservice class.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/CosmosDB-Solution-Accelerator-CosmosDB-Helper/9242e5f80141e6f33800cc73ee3b4f56143af76a/media/add todoservice class.png
--------------------------------------------------------------------------------
/media/azure-cosmos-db-create-new-account-detail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/CosmosDB-Solution-Accelerator-CosmosDB-Helper/9242e5f80141e6f33800cc73ee3b4f56143af76a/media/azure-cosmos-db-create-new-account-detail.png
--------------------------------------------------------------------------------
/media/dotnet new console.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/CosmosDB-Solution-Accelerator-CosmosDB-Helper/9242e5f80141e6f33800cc73ee3b4f56143af76a/media/dotnet new console.png
--------------------------------------------------------------------------------
/media/dotnet new worker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/CosmosDB-Solution-Accelerator-CosmosDB-Helper/9242e5f80141e6f33800cc73ee3b4f56143af76a/media/dotnet new worker.png
--------------------------------------------------------------------------------
/media/generate constructor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/CosmosDB-Solution-Accelerator-CosmosDB-Helper/9242e5f80141e6f33800cc73ee3b4f56143af76a/media/generate constructor.png
--------------------------------------------------------------------------------
/media/nuget package manager.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/CosmosDB-Solution-Accelerator-CosmosDB-Helper/9242e5f80141e6f33800cc73ee3b4f56143af76a/media/nuget package manager.png
--------------------------------------------------------------------------------
/media/override OnChangeFeedDataSets.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/CosmosDB-Solution-Accelerator-CosmosDB-Helper/9242e5f80141e6f33800cc73ee3b4f56143af76a/media/override OnChangeFeedDataSets.png
--------------------------------------------------------------------------------
/media/provision cosmosdb mongo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/CosmosDB-Solution-Accelerator-CosmosDB-Helper/9242e5f80141e6f33800cc73ee3b4f56143af76a/media/provision cosmosdb mongo.png
--------------------------------------------------------------------------------
/media/switch directory add package.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/CosmosDB-Solution-Accelerator-CosmosDB-Helper/9242e5f80141e6f33800cc73ee3b4f56143af76a/media/switch directory add package.png
--------------------------------------------------------------------------------
/media/switch directory add package2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/CosmosDB-Solution-Accelerator-CosmosDB-Helper/9242e5f80141e6f33800cc73ee3b4f56143af76a/media/switch directory add package2.png
--------------------------------------------------------------------------------
/media/worker project.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/CosmosDB-Solution-Accelerator-CosmosDB-Helper/9242e5f80141e6f33800cc73ee3b4f56143af76a/media/worker project.png
--------------------------------------------------------------------------------
/src/Libraries/Microsoft.Solutions.CosmosDB.Mongo/BusinessTransactionRepository.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT License.
3 |
4 | using MongoDB.Bson;
5 | using MongoDB.Bson.Serialization;
6 | using MongoDB.Driver;
7 | using MongoDB.Driver.Core;
8 | using System.Collections.Generic;
9 | using System.Threading.Tasks;
10 | using System.Linq;
11 |
12 |
13 | namespace Microsoft.Solutions.CosmosDB.Mongo
14 | {
15 | public class BusinessTransactionRepository : IRepository where TEntity : class, IEntityModel
16 | {
17 | private readonly IMongoDatabase _database;
18 |
19 | public BusinessTransactionRepository(IMongoClient client, string databaseName)
20 | {
21 | _database = client.GetDatabase(databaseName);
22 |
23 | if (!BsonClassMap.IsClassMapRegistered(typeof(TEntity)))
24 | BsonClassMap.RegisterClassMap();
25 | }
26 |
27 | public async Task GetAsync(TIdentifier id)
28 | {
29 | var result = await _database.GetCollection(typeof(TEntity).Name.ToLowerInvariant()).FindAsync(x => x.id.Equals(id));
30 | return await result.FirstOrDefaultAsync();
31 | }
32 |
33 | public async Task FindAsync(ISpecification specification)
34 | {
35 | var collection = _database.GetCollection(typeof(TEntity).Name.ToLowerInvariant());
36 | return await collection.Find(specification.Predicate).FirstOrDefaultAsync();
37 | }
38 |
39 |
40 | public async Task> FindAllAsync(FilterDefinition builders)
41 | {
42 | var collection = _database.GetCollection(typeof(TEntity).Name.ToLowerInvariant());
43 |
44 | return (await collection.FindAsync(builders)).ToList();
45 | }
46 |
47 |
48 | public async Task> FindAllAsync(ISpecification specification)
49 | {
50 | var collection = _database.GetCollection(typeof(TEntity).Name.ToLowerInvariant());
51 |
52 | GenericSpecification genericSpecification = specification as GenericSpecification;
53 |
54 | if (genericSpecification.OrderBy == null)
55 | {
56 | return (await collection.FindAsync(specification.Predicate)).ToList();
57 | }
58 | else if (genericSpecification.Order == Order.Asc)
59 | {
60 | return (await collection.FindAsync(specification.Predicate, new FindOptions() { Sort = Builders.Sort.Ascending(specification.OrderBy) })).ToList();
61 |
62 | }
63 | else if (genericSpecification.Order == Order.Desc)
64 | {
65 | return (await collection.FindAsync(specification.Predicate, new FindOptions() { Sort = Builders.Sort.Descending(specification.OrderBy) })).ToList();
66 | }
67 | else
68 | {
69 | return null;
70 | }
71 | }
72 |
73 |
74 | public async Task> GetAllAsync()
75 | {
76 | return (await _database.GetCollection(typeof(TEntity).Name.ToLowerInvariant()).FindAsync(new BsonDocument())).ToList();
77 |
78 | }
79 |
80 | public async Task> GetAllAsync(IEnumerable identifiers)
81 | {
82 |
83 | List results = new List();
84 | IMongoCollection collection = _database.GetCollection(typeof(TEntity).Name.ToLowerInvariant());
85 | foreach (var i in identifiers)
86 | {
87 | results.Add(await this.GetAsync(i));
88 | }
89 | return results;
90 | }
91 |
92 | public async Task SaveAsync(TEntity entity)
93 | {
94 | var collection = _database.GetCollection(typeof(TEntity).Name.ToLowerInvariant());
95 |
96 | await collection.ReplaceOneAsync(x => x.id.Equals(entity.id), entity, new ReplaceOptions
97 | {
98 | IsUpsert = true
99 | });
100 |
101 | return entity;
102 | }
103 |
104 | public async Task AddAsync(TEntity entity)
105 | {
106 | var collection = _database.GetCollection(typeof(TEntity).Name.ToLowerInvariant());
107 |
108 | await collection.ReplaceOneAsync(x => x.id.Equals(entity.id), entity, new ReplaceOptions
109 | {
110 | IsUpsert = true
111 | });
112 |
113 | return entity;
114 | }
115 |
116 | public async Task DeleteAsync(TIdentifier entityId, dynamic partitionKeyValue = null)
117 | {
118 | var collection = _database.GetCollection(typeof(TEntity).Name.ToLowerInvariant());
119 |
120 | await collection.DeleteOneAsync(x => x.id.Equals(entityId));
121 | }
122 |
123 | public async Task DeleteAsync(TEntity entity, dynamic partitionKeyValue = null)
124 | {
125 | var collection = _database.GetCollection(typeof(TEntity).Name.ToLowerInvariant());
126 |
127 | await collection.DeleteOneAsync(x => x.id.Equals(entity.id));
128 | }
129 |
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/src/Libraries/Microsoft.Solutions.CosmosDB.Mongo/Microsoft.Solutions.CosmosDB.Mongo.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net5.0
5 | Microsoft CosmosDB Solution Accelerator - CosmosDB Helper for Mongo API
6 | EAE.Solutions.CosmosDB.Mongo
7 | 0.7.3
8 | Microsoft Solutions
9 | Microsoft Corporation
10 | This library helps using CosmosDB to developers...
11 | true
12 | https://github.com/microsoft/CosmosDB-Solution-Accelerator-CosmosDB-Helper
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/Libraries/Microsoft.Solutions.CosmosDB.Mongo/MongoEntntyCollectionBase.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT License.
3 |
4 | using MongoDB.Driver;
5 | using System;
6 |
7 | namespace Microsoft.Solutions.CosmosDB.Mongo
8 | {
9 | public class MongoEntntyCollectionBase : IDataRepositoryProvider
10 | where TEntity : class, IEntityModel
11 | {
12 | public IRepository EntityCollection { get; init; }
13 |
14 | public MongoEntntyCollectionBase(string DataConnectionString, string CollectionName)
15 | {
16 | CosmosMongoClientManager.DataconnectionString = DataConnectionString;
17 | MongoClient _client = CosmosMongoClientManager.Instance;
18 |
19 | this.EntityCollection =
20 | new BusinessTransactionRepository(_client,
21 | CollectionName);
22 |
23 | }
24 | }
25 |
26 | public sealed class CosmosMongoClientManager
27 | {
28 | private CosmosMongoClientManager() { }
29 |
30 | static CosmosMongoClientManager()
31 | {
32 | }
33 |
34 | public static string DataconnectionString;
35 |
36 | private static readonly Lazy _instance =
37 | new Lazy(() => new MongoClient(CosmosMongoClientManager.DataconnectionString));
38 |
39 | public static MongoClient Instance
40 | {
41 | get { return _instance.Value; }
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/Libraries/Microsoft.Solutions.CosmosDB.SQL.ChangeFeed/ChangeFeedProcessorHelper.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT License.
3 |
4 | using Microsoft.Azure.Cosmos;
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Linq;
8 | using System.Text;
9 | using System.Threading.Tasks;
10 |
11 | namespace Microsoft.Solutions.CosmosDB.SQL.ChangeFeed
12 | {
13 | public class ChangeFeedProcessHelper
14 | {
15 | public async Task InitChangeFeedProcessorAsync(
16 | string DataConnectionString,
17 | string SourceDatabaseName,
18 | string MonitoredContainerName,
19 | Container.ChangesHandler ChangeHandler
20 | )
21 | {
22 | Container leaseContainer;
23 | Database database;
24 | string leaseContainerName = $"{MonitoredContainerName}_lease";
25 | var processorName = $"{MonitoredContainerName}_changefeedwatcher";
26 | var instanceName = $"{processorName}_host_{Guid.NewGuid().ToString().Substring(0,8)}";
27 |
28 | //Initialize CosmosDB Connection
29 | CosmosClient cosmosClient = new CosmosClient(DataConnectionString);
30 |
31 | database = cosmosClient.GetDatabase(SourceDatabaseName);
32 | if (database is null) throw new NullReferenceException("Specified Database doesn't exist");
33 |
34 | leaseContainer = await database.CreateContainerIfNotExistsAsync(leaseContainerName, "/partitionKey");
35 |
36 | ChangeFeedProcessor changeFeedProcessor = database.GetContainer(MonitoredContainerName)
37 | .GetChangeFeedProcessorBuilder(processorName: processorName, ChangeHandler)
38 | .WithInstanceName(instanceName)
39 | .WithLeaseContainer(leaseContainer)
40 | .Build();
41 |
42 | Console.WriteLine($"Starting Change Feed Processor...{processorName} in {instanceName}");
43 | await changeFeedProcessor.StartAsync();
44 | Console.WriteLine($"Change Feed Processor {processorName} started in {instanceName}");
45 | return changeFeedProcessor;
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/Libraries/Microsoft.Solutions.CosmosDB.SQL.ChangeFeed/Microsoft.Solutions.CosmosDB.SQL.ChangeFeed.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net5.0
5 | Microsoft CosmosDB Solution Accelerator - CosmosDB Helper for SQL(using SDK)
6 | EAE.Solutions.CosmosDB.SQL.ChangeFeed
7 | 0.7.3
8 | Microsoft Solutions
9 | Microsoft Corporation
10 | This library helps using CosmosDB to developers...
11 | true
12 | https://github.com/microsoft/CosmosDB-Solution-Accelerator-CosmosDB-Helper
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/Libraries/Microsoft.Solutions.CosmosDB.SQL.ChangeFeed/Watcher.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT License.
3 |
4 | using Microsoft.Azure.Cosmos;
5 | using Microsoft.Extensions.Configuration;
6 | using Microsoft.Extensions.Hosting;
7 | using System;
8 | using System.Collections.Generic;
9 | using System.Linq;
10 | using System.Text;
11 | using System.Threading;
12 | using System.Threading.Tasks;
13 | using Microsoft.Solutions.CosmosDB.SQL;
14 |
15 | namespace Microsoft.Solutions.CosmosDB.SQL.ChangeFeed
16 | {
17 | public class Watcher : BackgroundService
18 | {
19 | readonly string dataConnectionString;
20 | readonly string sourceDatabaseName;
21 | readonly string sourceContainerName;
22 |
23 | private ChangeFeedProcessor changeFeedProcessor;
24 |
25 | public Watcher(string ConnectionString, string MonitoredDatabaseName, string MonitoredContainerName)
26 | {
27 | dataConnectionString = ConnectionString;
28 | sourceDatabaseName = MonitoredDatabaseName;
29 | sourceContainerName = MonitoredContainerName;
30 |
31 | }
32 |
33 | public override async Task StartAsync(CancellationToken cancellationToken)
34 | {
35 | ChangeFeedProcessHelper changeFeedWatcher = new ChangeFeedProcessHelper();
36 | changeFeedProcessor = await changeFeedWatcher.InitChangeFeedProcessorAsync(dataConnectionString, sourceDatabaseName, sourceContainerName, HandleChangesAsync);
37 | Console.WriteLine("Change feed watcher started");
38 | }
39 |
40 | public override async Task StopAsync(CancellationToken cancellationToken)
41 | {
42 | await changeFeedProcessor.StopAsync();
43 | Console.WriteLine("Change feed watcher stopped");
44 | }
45 |
46 | protected async Task HandleChangesAsync(IReadOnlyCollection changes, CancellationToken cancellationToken)
47 | {
48 | await OnChangedFeedDataSets(changes, cancellationToken);
49 |
50 | }
51 |
52 | protected virtual Task OnChangedFeedDataSets(IReadOnlyCollection changes, CancellationToken cancellationToken) {
53 | return null;
54 | }
55 |
56 |
57 | protected override async Task ExecuteAsync(CancellationToken stoppingToken)
58 | {
59 | while (!stoppingToken.IsCancellationRequested)
60 | {
61 | await Task.Delay(500, stoppingToken);
62 | }
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/Libraries/Microsoft.Solutions.CosmosDB.SQL/BusinessTransactionRepository.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT License.
3 |
4 | using Microsoft.Azure.Cosmos;
5 | using Microsoft.Azure.Cosmos.Linq;
6 | using System;
7 | using System.Collections.Generic;
8 | using System.Linq;
9 | using System.Threading.Tasks;
10 | using Microsoft.Solutions.CosmosDB;
11 |
12 | namespace Microsoft.Solutions.CosmosDB.SQL
13 | {
14 |
15 | public class BusinessTransactionRepository : IRepository where TEntity : class, IEntityModel
16 | {
17 | private readonly Database _database;
18 | private readonly Container _container;
19 | static bool _checkedDatabase = false;
20 | static bool _checkedContainer = false;
21 |
22 | public BusinessTransactionRepository(CosmosClient client, string DatabaseName, string containerName = "")
23 | {
24 | if (!BusinessTransactionRepository._checkedDatabase)
25 | {
26 | _database = client.CreateDatabaseIfNotExistsAsync(DatabaseName).Result;
27 | BusinessTransactionRepository._checkedDatabase = true;
28 | }
29 | else
30 | {
31 | _database = client.GetDatabase(DatabaseName);
32 | }
33 |
34 |
35 |
36 | if (string.IsNullOrEmpty(containerName))
37 | {
38 | if (BusinessTransactionRepository._checkedContainer)
39 | {
40 | _container = _database.GetContainer(typeof(TEntity).Name + "s");
41 | }
42 | else
43 | {
44 | _container = _database.CreateContainerIfNotExistsAsync(typeof(TEntity).Name + "s", "/__partitionkey").Result;
45 | BusinessTransactionRepository._checkedContainer = true;
46 | }
47 | }
48 | else
49 | {
50 | if (BusinessTransactionRepository._checkedContainer)
51 | {
52 | _container = _database.GetContainer(containerName);
53 | }
54 | else
55 | {
56 | try
57 | {
58 | //Try to check it is in the database
59 | _container = _database.CreateContainerAsync(containerName, "/__partitionkey").Result;
60 | BusinessTransactionRepository._checkedContainer = true;
61 | }
62 | catch (Exception ex)
63 | {
64 | var cosmosException = ex.InnerException as CosmosException;
65 |
66 | if ((cosmosException) != null)
67 | if (cosmosException.StatusCode == System.Net.HttpStatusCode.Conflict)
68 | {
69 | _container = _database.GetContainer(containerName);
70 | BusinessTransactionRepository._checkedContainer = true;
71 | }
72 | }
73 | }
74 | }
75 | }
76 |
77 |
78 | public async Task GetAsync(TIdentifier id)
79 | {
80 | var iterator = this._container.GetItemQueryIterator($"select * from c where c.id = '{id.ToString()}'");
81 |
82 | while (iterator.HasMoreResults)
83 | {
84 | foreach (var item in await iterator.ReadNextAsync())
85 | {
86 | return item;
87 | }
88 | }
89 |
90 | return null;
91 | }
92 |
93 | public async Task AddAsync(TEntity entity)
94 | {
95 | var result = await this._container.CreateItemAsync(entity);
96 | return result.Resource;
97 | }
98 |
99 | public async Task FindAsync(ISpecification specification)
100 | {
101 | var iterator = this._container.GetItemLinqQueryable().Where(specification.Predicate).ToFeedIterator();
102 |
103 | while (iterator.HasMoreResults)
104 | {
105 | foreach (var item in await iterator.ReadNextAsync())
106 | {
107 | return item;
108 | }
109 | }
110 |
111 | return null;
112 | }
113 |
114 | public async Task> GetAllAsync()
115 | {
116 | var iterator = this._container.GetItemLinqQueryable().ToFeedIterator();
117 |
118 | List results = new List();
119 |
120 | while (iterator.HasMoreResults)
121 | {
122 | var response = await iterator.ReadNextAsync();
123 | foreach (var item in response)
124 | {
125 | results.Add(item);
126 | }
127 | }
128 |
129 | return results;
130 | }
131 |
132 | public async Task> FindAllAsync(ISpecification specification)
133 | {
134 | GenericSpecification genericSpecification = specification as GenericSpecification;
135 |
136 | FeedIterator iterator = null;
137 |
138 | if (genericSpecification.OrderBy == null)
139 | {
140 | iterator = this._container.GetItemLinqQueryable().Where(specification.Predicate).ToFeedIterator();
141 | }
142 | else
143 | {
144 | if (genericSpecification.Order == Order.Asc)
145 | {
146 | iterator = this._container.GetItemLinqQueryable().Where(specification.Predicate).OrderBy(specification.OrderBy).ToFeedIterator();
147 | }
148 | else
149 | {
150 | iterator = this._container.GetItemLinqQueryable().Where(specification.Predicate).OrderByDescending(specification.OrderBy).ToFeedIterator();
151 | }
152 | }
153 |
154 | List results = new List();
155 |
156 | while (iterator.HasMoreResults)
157 | {
158 | var response = await iterator.ReadNextAsync();
159 | foreach (var item in response)
160 | {
161 | results.Add(item);
162 | }
163 | }
164 |
165 | return results;
166 | }
167 |
168 | public async Task> GetAllAsync(IEnumerable identifiers)
169 | {
170 | List results = new List();
171 |
172 | foreach (var id in identifiers)
173 | {
174 | var iterator = this._container.GetItemQueryIterator($"select * from c where c.id = '{id.ToString()}'");
175 |
176 | while (iterator.HasMoreResults)
177 | {
178 | var response = await iterator.ReadNextAsync();
179 | foreach (var item in response)
180 | {
181 | results.Add(item);
182 | }
183 | }
184 | }
185 |
186 | return results;
187 |
188 | }
189 |
190 | public async Task SaveAsync(TEntity entity)
191 | {
192 | var result = await this._container.ReplaceItemAsync(entity, entity.id.ToString());
193 | return result.Resource;
194 |
195 | }
196 |
197 | public async Task DeleteAsync(TIdentifier EntityId, dynamic partitionKeyValue = null)
198 | {
199 | var cosmosEntity = await this.GetAsync(EntityId) as TEntity;
200 |
201 | if (partitionKeyValue == null)
202 | {
203 | await this._container.DeleteItemAsync(cosmosEntity.id.ToString(), new PartitionKey(cosmosEntity.__partitionkey));
204 | }
205 | else
206 | {
207 | await this._container.DeleteItemAsync(cosmosEntity.id.ToString(), new PartitionKey(partitionKeyValue));
208 | }
209 | }
210 |
211 | public async Task DeleteAsync(TEntity entity, dynamic partitionKeyValue = null)
212 | {
213 | var cosmosEntity = entity as CosmosDBEntityBase;
214 |
215 | if (partitionKeyValue == null)
216 | {
217 | await this._container.DeleteItemAsync(entity.id.ToString(), new PartitionKey(cosmosEntity.__partitionkey));
218 | }
219 | else
220 | {
221 | await this._container.DeleteItemAsync(entity.id.ToString(), new PartitionKey(partitionKeyValue));
222 | }
223 |
224 | }
225 |
226 | public async Task Find(ISpecification specification)
227 | {
228 | var iterator = this._container.GetItemLinqQueryable().Where(specification.Predicate).ToFeedIterator();
229 |
230 | while (iterator.HasMoreResults)
231 | {
232 | foreach (var item in await iterator.ReadNextAsync())
233 | {
234 | return item;
235 | }
236 | }
237 |
238 | return null;
239 | }
240 | }
241 | }
242 |
--------------------------------------------------------------------------------
/src/Libraries/Microsoft.Solutions.CosmosDB.SQL/Microsoft.Solutions.CosmosDB.SQL.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net5.0
5 | Microsoft CosmosDB Solution Accelerator - CosmosDB Helper for SQL(using SDK)
6 | EAE.Solutions.CosmosDB.SQL
7 | 0.7.3
8 | Microsoft Solutions
9 | Microsoft Corporation
10 | This library helps using CosmosDB to developers...
11 | true
12 | https://github.com/microsoft/CosmosDB-Solution-Accelerator-CosmosDB-Helper
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/Libraries/Microsoft.Solutions.CosmosDB.SQL/SQLEntityCollectionBase.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT License.
3 |
4 | using Microsoft.Azure.Cosmos;
5 | using System;
6 | using System.Diagnostics;
7 |
8 | namespace Microsoft.Solutions.CosmosDB.SQL
9 | {
10 | public class SQLEntityCollectionBase : IDataRepositoryProvider
11 | where TEntity : class, IEntityModel
12 | {
13 | public IRepository EntityCollection { get ; init ; }
14 |
15 | ///
16 | ///
17 | ///
18 | /// Connection String
19 | /// Your Database Name
20 | /// (Optional) If you don't pass it, The Container will be created by Entity Model Class Name + "s", In Model First Dev, You don't need to use it
21 | public SQLEntityCollectionBase(string DataConnectionString, string CollectionName, string ContainerName = "")
22 | {
23 | CosmosClientManager.DataconnectionString = DataConnectionString;
24 | CosmosClient _client = CosmosClientManager.Instance;
25 |
26 | this.EntityCollection =
27 | new BusinessTransactionRepository(_client,
28 | CollectionName, ContainerName);
29 |
30 | }
31 | }
32 |
33 | public sealed class CosmosClientManager
34 | {
35 | private CosmosClientManager() { }
36 |
37 |
38 | static CosmosClientManager()
39 | {
40 | //Type defaultTrace = Type.GetType("Microsoft.Azure.Cosmos.Core.Trace.DefaultTrace,Microsoft.Azure.Cosmos.Direct");
41 | //TraceSource traceSource = (TraceSource)defaultTrace.GetProperty("TraceSource").GetValue(null);
42 | //traceSource.Switch.Level = SourceLevels.Off;
43 | //traceSource.Listeners.Clear();
44 | }
45 |
46 | public static string DataconnectionString;
47 |
48 | private static readonly Lazy _instance =
49 | new Lazy(() => new CosmosClient(CosmosClientManager.DataconnectionString));
50 |
51 | public static CosmosClient Instance
52 | {
53 | get { return _instance.Value; }
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/Libraries/Microsoft.Solutions.CosmosDB.Test/CosmosDBTest.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT License.
3 |
4 | using Microsoft.VisualStudio.TestTools.UnitTesting;
5 | using System.Threading.Tasks;
6 | using System.Linq;
7 | using System;
8 | using Microsoft.Solutions.CosmosDB.Mongo;
9 | using Microsoft.Solutions.CosmosDB.SQL;
10 | using System.Collections.Generic;
11 |
12 | namespace Microsoft.Solutions.CosmosDB.Test
13 | {
14 | [TestClass]
15 | public class CosmosDBLibTest
16 | {
17 | public static IRepository repository = null;
18 |
19 | private static string cosmossqlConn = "{PUT YOUR COSMOS SQL Core API CONNECTION STRING}";
20 | private static string cosmosmongoConn = "{PUT YOUR COSMOS MONGO API CONNECTION STRING}";
21 |
22 | private static dynamic Repository;
23 |
24 | [TestInitialize]
25 | public void TestInit()
26 | {
27 | //Mongo Test
28 | //Repository = new MongoRepository(cosmosmongoConn, "MongoTEST");
29 |
30 |
31 |
32 | //SQL SDK Test
33 | Repository = new CosmosSQLRepository(cosmossqlConn, "SDKTEST");
34 |
35 | }
36 |
37 | [TestMethod]
38 | public async Task TEST01_AddAsync()
39 | {
40 | await repository.AddAsync(new Person() { name = "person1", age = 20, gender = Person.Gender.Female, title = "employee" });
41 | await repository.AddAsync(new Person() { name = "person2", age = 20, gender = Person.Gender.Female, title = "employee" });
42 | await repository.AddAsync(new Person() { name = "person3", age = 20, gender = Person.Gender.Female, title = "employee" });
43 | await repository.AddAsync(new Person() { name = "person4", age = 20, gender = Person.Gender.Female, title = "employee" });
44 | }
45 |
46 | [TestMethod]
47 | public async Task TEST02_SaveAsync()
48 | {
49 | var person1 = await repository.FindAsync(new GenericSpecification(x => x.name == "person1"));
50 | person1.age = 30;
51 |
52 | var person2 = await repository.FindAsync(new GenericSpecification(x => x.name == "person2"));
53 | person2.age = 32;
54 |
55 | var result_person1 = await repository.SaveAsync(person1);
56 | var result_person2 = await repository.SaveAsync(person2);
57 |
58 | Assert.AreEqual(result_person1.age, 30);
59 | Assert.AreEqual(result_person2.age, 32);
60 |
61 | }
62 |
63 | [TestMethod]
64 | public async Task TEST03_Find()
65 | {
66 | var people = await repository.FindAllAsync(new GenericSpecification(x => x.name.StartsWith("person")));
67 | Assert.IsTrue(people.Count() > 0);
68 | }
69 |
70 | [TestMethod]
71 | public async Task TEST04_Get()
72 | {
73 | var person = await repository.FindAsync(new GenericSpecification(x => x.name == "person1"));
74 | var retperson = await repository.GetAsync(person.id);
75 |
76 | Assert.AreEqual(person.name, retperson.name);
77 | }
78 |
79 | [TestMethod]
80 | public async Task TEST05_FindAllAsync()
81 | {
82 | var results = await repository.FindAllAsync(new GenericSpecification(x => x.age > 10));
83 |
84 | Console.WriteLine($"{results.Count()} records has been found");
85 | foreach (var item in results)
86 | {
87 | System.Console.WriteLine($"{item.name} - {item.gender} - {item.title} - {item.age}");
88 | }
89 |
90 | Console.WriteLine($"Order by name ASC");
91 | results = await repository.FindAllAsync(new GenericSpecification(x => x.age > 10, x => x.name, Order.Asc));
92 | foreach (var item in results)
93 | {
94 | System.Console.WriteLine($"{item.name} - {item.gender} - {item.title} - {item.age}");
95 | }
96 |
97 | Console.WriteLine($"Order by name DESC");
98 | results = await repository.FindAllAsync(new GenericSpecification(x => x.age > 10, x => x.name, Order.Desc));
99 | foreach (var item in results)
100 | {
101 | System.Console.WriteLine($"{item.name} - {item.gender} - {item.title} - {item.age}");
102 | }
103 |
104 |
105 | Assert.AreNotSame(0, results.Count());
106 | }
107 |
108 | [TestMethod]
109 | public async Task TEST06_GetAllAsync()
110 | {
111 | var results = await repository.GetAllAsync();
112 | Console.WriteLine($"{results.Count()} records has been recorded");
113 |
114 | Assert.AreNotEqual(results.Count(), 0);
115 | }
116 |
117 | [TestMethod]
118 | public async Task TEST07_FindAllAsync()
119 | {
120 | var _over30agedpeople = await repository.FindAllAsync(new GenericSpecification(x => x.age > 30));
121 | var results = await repository.GetAllAsync(_over30agedpeople.Select(x => x.id).ToArray());
122 |
123 | Console.WriteLine($"{results.Count()} objsts has been recorded");
124 | Assert.AreEqual(results.Count(), _over30agedpeople.Count());
125 | }
126 |
127 | [TestMethod]
128 | public async Task TEST08_DeleteAsync()
129 | {
130 | var _30agedperson = await repository.FindAsync(new GenericSpecification(x => x.age == 30));
131 | _30agedperson.title = "employeer";
132 |
133 | await repository.DeleteAsync(_30agedperson);
134 |
135 | Console.WriteLine($"{_30agedperson.id} object has been deleted");
136 | }
137 |
138 | [TestMethod]
139 | public async Task TEST09_DeleteAsync()
140 | {
141 | var _30agedperson = await repository.FindAsync(new GenericSpecification(x => x.age == 32));
142 | _30agedperson.title = "employeer";
143 |
144 | await repository.DeleteAsync(_30agedperson.id);
145 |
146 | Console.WriteLine($"{_30agedperson.id} object has been deleted");
147 | }
148 | }
149 |
150 | public class MongoRepository : MongoEntntyCollectionBase
151 | {
152 | public MongoRepository(string DataConnectionString, string CollectionName) : base(DataConnectionString, CollectionName)
153 | {
154 | CosmosDBLibTest.repository = this.EntityCollection;
155 | }
156 | }
157 |
158 | public class CosmosSQLRepository : SQLEntityCollectionBase
159 | {
160 | public CosmosSQLRepository(string DataConnectionString, string CollectionName) : base(DataConnectionString, CollectionName)
161 | {
162 | CosmosDBLibTest.repository = this.EntityCollection;
163 | }
164 | }
165 |
166 | public class Person : CosmosDBEntityBase
167 | {
168 | public string name { get; set; }
169 | public int age { get; set; }
170 | public string title { get; set; }
171 | public Gender gender { get; set; }
172 | public enum Gender { Male, Female, NoN }
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/src/Libraries/Microsoft.Solutions.CosmosDB.Test/Microsoft.Solutions.CosmosDB.Test.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net5.0
5 |
6 | false
7 |
8 |
9 |
10 | 1701;1702;CS0414
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | all
19 | runtime; build; native; contentfiles; analyzers; buildtransitive
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/Libraries/Microsoft.Solutions.CosmosDB/CosmosDBEntityBase.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT License.
3 |
4 | using System;
5 | using System.Security.Cryptography;
6 | using System.Text;
7 |
8 | namespace Microsoft.Solutions.CosmosDB
9 | {
10 | public class CosmosDBEntityBase : IEntityModel
11 | {
12 | public CosmosDBEntityBase()
13 | {
14 | this.id = Guid.NewGuid().ToString();
15 | this.__partitionkey = CosmosDBEntityBase.GetKey(id, 9999);
16 | }
17 |
18 | ///
19 | /// id will be generated automatically. you don't need to manage it by yourself
20 | ///
21 | public string id { get; set; }
22 |
23 | ///
24 | /// the partitionkey will be used for storage partitioning. you don't need to manage it by yourself
25 | ///
26 | public string __partitionkey { get; set; }
27 |
28 | static SHA1 _sha1;
29 |
30 | static CosmosDBEntityBase()
31 | {
32 | _sha1 = SHA1.Create();
33 | }
34 |
35 | ///
36 | /// Generate partitionkey for CosmosDB
37 | /// using SHA1 hash with id, convert it to uint and divide with number of partitions
38 | /// assigned default value as 9999 (9999 partition at this moment)
39 | ///
40 | ///
41 | ///
42 | ///
43 | public static string GetKey(string id, int numberofPartitions)
44 | {
45 | var hasedVal = _sha1.ComputeHash(Encoding.UTF8.GetBytes(id));
46 | var intHashedVal = BitConverter.ToUInt32(hasedVal, 0);
47 |
48 | var range = numberofPartitions - 1;
49 | var length = range.ToString().Length;
50 |
51 | var key = (intHashedVal % numberofPartitions).ToString();
52 | return key.PadLeft(length, '0');
53 | }
54 |
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/Libraries/Microsoft.Solutions.CosmosDB/GenericSpecification.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT License.
3 |
4 | using System;
5 | using System.Linq.Expressions;
6 |
7 | namespace Microsoft.Solutions.CosmosDB
8 | {
9 | public class GenericSpecification : ISpecification
10 | {
11 | public GenericSpecification(Expression> predicate, Expression> orderBy = null, Order order = Order.Asc)
12 | {
13 | Predicate = predicate;
14 | OrderBy = orderBy;
15 | Order = order;
16 | }
17 | ///
18 | /// Gets or sets the func delegate query to execute against the repository for searching records.
19 | ///
20 | public Expression> Predicate { get; }
21 | public Expression> OrderBy { get; }
22 | public Order Order { get; }
23 | }
24 |
25 | public enum Order
26 | {
27 | Asc,
28 | Desc
29 | }
30 | }
--------------------------------------------------------------------------------
/src/Libraries/Microsoft.Solutions.CosmosDB/IDataRepositoryProvider.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT License.
3 |
4 | namespace Microsoft.Solutions.CosmosDB
5 | {
6 | ///
7 | /// Interface for DI in each CosmosDB Helpers
8 | ///
9 | ///
10 | public interface IDataRepositoryProvider
11 | {
12 | ///
13 | /// Entity Object Collections which has Database CRUD operations
14 | ///
15 | IRepository EntityCollection { get; init ; }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/Libraries/Microsoft.Solutions.CosmosDB/IEntityModel.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT License.
3 |
4 | namespace Microsoft.Solutions.CosmosDB
5 | {
6 | ///
7 | /// Every Entnties have to follow this interface
8 | /// Unique identifier type should be string
9 | ///
10 | ///
11 | public interface IEntityModel
12 | {
13 | TIdentifier id { get; set; }
14 | string __partitionkey { get; set; }
15 | }
16 | }
--------------------------------------------------------------------------------
/src/Libraries/Microsoft.Solutions.CosmosDB/IRepository.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT License.
3 |
4 | using System.Collections.Generic;
5 | using System.Threading.Tasks;
6 |
7 | namespace Microsoft.Solutions.CosmosDB
8 | {
9 | ///
10 | /// Default CRUD operations in CosmosDB
11 | ///
12 | ///
13 | ///
14 | public interface IRepository
15 | {
16 | Task AddAsync(TEntity entity);
17 | Task DeleteAsync(TEntity entit, dynamic partitionKeyValue = null);
18 | Task DeleteAsync(TIdentifier entityId, dynamic partitionKeyValue = null);
19 | Task FindAsync(ISpecification specification);
20 | Task> FindAllAsync(ISpecification specification);
21 | Task GetAsync(TIdentifier id);
22 | Task> GetAllAsync();
23 | Task> GetAllAsync(IEnumerable identifiers);
24 | Task SaveAsync(TEntity entity);
25 | }
26 | }
--------------------------------------------------------------------------------
/src/Libraries/Microsoft.Solutions.CosmosDB/ISpecification.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT License.
3 |
4 | using System;
5 | using System.Linq.Expressions;
6 |
7 | namespace Microsoft.Solutions.CosmosDB
8 | {
9 | public interface ISpecification
10 | {
11 | ///
12 | /// Gets or sets the func delegate query to execute against the repository for searching records.
13 | ///
14 | Expression> Predicate { get; }
15 | Expression> OrderBy { get; }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/Libraries/Microsoft.Solutions.CosmosDB/Microsoft.Solutions.CosmosDB.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net5.0
5 | https://github.com/microsoft/CosmosDB-Solution-Accelerator-CosmosDB-Helper
6 | EAE.Solutions.CosmosDB
7 | 0.7.3
8 | Microsoft Solutions
9 | Microsoft Corporation
10 | True
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/Microsoft CosmosDB Solution Accelerator.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.1.31911.260
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{E36FC976-3345-4988-B710-C7F5DEAD2EF6}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Solutions.CosmosDB.Mongo.TODO.Service", "Sample\Microsoft.Solutions.CosmosDB.Mongo.TODO.Service\Microsoft.Solutions.CosmosDB.Mongo.TODO.Service.csproj", "{9AD83669-5DE8-44E5-9C12-BAD90FB93A23}"
9 | EndProject
10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Solutions.CosmosDB.Mongo.TODO.Tests", "Sample\Microsoft.Solutions.CosmosDB.Mongo.TODO.Tests\Microsoft.Solutions.CosmosDB.Mongo.TODO.Tests.csproj", "{E36ADD7C-3E12-44D5-9A56-0B5C086EF755}"
11 | EndProject
12 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Mongo", "Mongo", "{1FE0C1A9-B34A-4B9A-8B13-9342D28B849E}"
13 | EndProject
14 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libraries", "Libraries", "{F75FAB67-13B6-4A4D-8FD9-C30D4A7B648F}"
15 | EndProject
16 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Solutions.CosmosDB.SQL", "libraries\Microsoft.Solutions.CosmosDB.SQL\Microsoft.Solutions.CosmosDB.SQL.csproj", "{A161FC5B-E3D9-4814-BFFB-90FD8AE1E158}"
17 | EndProject
18 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SQL", "SQL", "{9CF5C149-650A-42C4-A08E-0A066FE7721A}"
19 | EndProject
20 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Solutions.CosmosDB.SQL.TODO.Service", "Sample\Microsoft.Solutions.CosmosDB.SQL.SDK.TODO.Service\Microsoft.Solutions.CosmosDB.SQL.TODO.Service.csproj", "{79FBDE75-2C12-4684-ADCB-C8004D305373}"
21 | EndProject
22 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Solutions.CosmosDB.SQL.TODO.Service.Tests", "Sample\Microsoft.Solutions.CosmosDB.SQL.SDK.TODO.Service.Tests\Microsoft.Solutions.CosmosDB.SQL.TODO.Service.Tests.csproj", "{7C6EAD80-D219-4792-98D7-247248918968}"
23 | EndProject
24 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Solutions.CosmosDB", "libraries\Microsoft.Solutions.CosmosDB\Microsoft.Solutions.CosmosDB.csproj", "{5CF6B6AA-635A-46A3-A0BC-A84294BB205E}"
25 | EndProject
26 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Solutions.CosmosDB.TODO.WebHost", "Sample\Microsoft.Solutions.CosmosDB.WebHost\Microsoft.Solutions.CosmosDB.TODO.WebHost.csproj", "{8926C6B9-213D-4569-A878-53204473E75E}"
27 | EndProject
28 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Solutions.CosmosDB.SQL.ChangeFeed", "Libraries\Microsoft.Solutions.CosmosDB.SQL.ChangeFeed\Microsoft.Solutions.CosmosDB.SQL.ChangeFeed.csproj", "{45D30D7D-271F-4833-8E80-09831F79F1E5}"
29 | EndProject
30 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Solutions.CosmosDB.SQL.ChangeFeed.Service", "Sample\Microsoft.Solutions.CosmosDB.SQL.ChangeFeed.Service\Microsoft.Solutions.CosmosDB.SQL.ChangeFeed.Service.csproj", "{0F6953CF-37F3-4759-AF46-A62ABB49D76C}"
31 | EndProject
32 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Solutions.CosmosDB.Test", "libraries\Microsoft.Solutions.CosmosDB.Test\Microsoft.Solutions.CosmosDB.Test.csproj", "{228A0A82-EF20-459D-A9CD-564EC02A45E2}"
33 | EndProject
34 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Solutions.CosmosDB.Security.ManagedIdentity", "libraries\Microsoft.Solutions.CosmosDB.Security.ManagedIdentity\Microsoft.Solutions.CosmosDB.Security.ManagedIdentity.csproj", "{88B10D30-4A93-4BC0-9CF5-F813B40A6943}"
35 | EndProject
36 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Utils", "Utils", "{1E21D3A9-D00F-45AF-99EC-BF8123ACE33F}"
37 | EndProject
38 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Solutions.HTTP", "Utils\Microsoft.Solutions.HTTP\Microsoft.Solutions.HTTP.csproj", "{50FC98FF-EAE1-478D-B9F9-846DA11372AD}"
39 | EndProject
40 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Solutions.CosmosDB.Mongo", "libraries\Microsoft.Solutions.CosmosDB.Mongo\Microsoft.Solutions.CosmosDB.Mongo.csproj", "{43EAD90D-01D0-4468-BD44-86D20A88F947}"
41 | EndProject
42 | Global
43 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
44 | Debug|Any CPU = Debug|Any CPU
45 | DebugWithSymbol|Any CPU = DebugWithSymbol|Any CPU
46 | Release|Any CPU = Release|Any CPU
47 | EndGlobalSection
48 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
49 | {9AD83669-5DE8-44E5-9C12-BAD90FB93A23}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
50 | {9AD83669-5DE8-44E5-9C12-BAD90FB93A23}.Debug|Any CPU.Build.0 = Debug|Any CPU
51 | {9AD83669-5DE8-44E5-9C12-BAD90FB93A23}.DebugWithSymbol|Any CPU.ActiveCfg = Debug|Any CPU
52 | {9AD83669-5DE8-44E5-9C12-BAD90FB93A23}.DebugWithSymbol|Any CPU.Build.0 = Debug|Any CPU
53 | {9AD83669-5DE8-44E5-9C12-BAD90FB93A23}.Release|Any CPU.ActiveCfg = Release|Any CPU
54 | {9AD83669-5DE8-44E5-9C12-BAD90FB93A23}.Release|Any CPU.Build.0 = Release|Any CPU
55 | {E36ADD7C-3E12-44D5-9A56-0B5C086EF755}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
56 | {E36ADD7C-3E12-44D5-9A56-0B5C086EF755}.Debug|Any CPU.Build.0 = Debug|Any CPU
57 | {E36ADD7C-3E12-44D5-9A56-0B5C086EF755}.DebugWithSymbol|Any CPU.ActiveCfg = Debug|Any CPU
58 | {E36ADD7C-3E12-44D5-9A56-0B5C086EF755}.DebugWithSymbol|Any CPU.Build.0 = Debug|Any CPU
59 | {E36ADD7C-3E12-44D5-9A56-0B5C086EF755}.Release|Any CPU.ActiveCfg = Release|Any CPU
60 | {E36ADD7C-3E12-44D5-9A56-0B5C086EF755}.Release|Any CPU.Build.0 = Release|Any CPU
61 | {A161FC5B-E3D9-4814-BFFB-90FD8AE1E158}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
62 | {A161FC5B-E3D9-4814-BFFB-90FD8AE1E158}.Debug|Any CPU.Build.0 = Debug|Any CPU
63 | {A161FC5B-E3D9-4814-BFFB-90FD8AE1E158}.DebugWithSymbol|Any CPU.ActiveCfg = Debug|Any CPU
64 | {A161FC5B-E3D9-4814-BFFB-90FD8AE1E158}.DebugWithSymbol|Any CPU.Build.0 = Debug|Any CPU
65 | {A161FC5B-E3D9-4814-BFFB-90FD8AE1E158}.Release|Any CPU.ActiveCfg = Release|Any CPU
66 | {A161FC5B-E3D9-4814-BFFB-90FD8AE1E158}.Release|Any CPU.Build.0 = Release|Any CPU
67 | {79FBDE75-2C12-4684-ADCB-C8004D305373}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
68 | {79FBDE75-2C12-4684-ADCB-C8004D305373}.Debug|Any CPU.Build.0 = Debug|Any CPU
69 | {79FBDE75-2C12-4684-ADCB-C8004D305373}.DebugWithSymbol|Any CPU.ActiveCfg = Debug|Any CPU
70 | {79FBDE75-2C12-4684-ADCB-C8004D305373}.DebugWithSymbol|Any CPU.Build.0 = Debug|Any CPU
71 | {79FBDE75-2C12-4684-ADCB-C8004D305373}.Release|Any CPU.ActiveCfg = Release|Any CPU
72 | {79FBDE75-2C12-4684-ADCB-C8004D305373}.Release|Any CPU.Build.0 = Release|Any CPU
73 | {7C6EAD80-D219-4792-98D7-247248918968}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
74 | {7C6EAD80-D219-4792-98D7-247248918968}.Debug|Any CPU.Build.0 = Debug|Any CPU
75 | {7C6EAD80-D219-4792-98D7-247248918968}.DebugWithSymbol|Any CPU.ActiveCfg = Debug|Any CPU
76 | {7C6EAD80-D219-4792-98D7-247248918968}.DebugWithSymbol|Any CPU.Build.0 = Debug|Any CPU
77 | {7C6EAD80-D219-4792-98D7-247248918968}.Release|Any CPU.ActiveCfg = Release|Any CPU
78 | {7C6EAD80-D219-4792-98D7-247248918968}.Release|Any CPU.Build.0 = Release|Any CPU
79 | {5CF6B6AA-635A-46A3-A0BC-A84294BB205E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
80 | {5CF6B6AA-635A-46A3-A0BC-A84294BB205E}.Debug|Any CPU.Build.0 = Debug|Any CPU
81 | {5CF6B6AA-635A-46A3-A0BC-A84294BB205E}.DebugWithSymbol|Any CPU.ActiveCfg = Debug|Any CPU
82 | {5CF6B6AA-635A-46A3-A0BC-A84294BB205E}.DebugWithSymbol|Any CPU.Build.0 = Debug|Any CPU
83 | {5CF6B6AA-635A-46A3-A0BC-A84294BB205E}.Release|Any CPU.ActiveCfg = Release|Any CPU
84 | {5CF6B6AA-635A-46A3-A0BC-A84294BB205E}.Release|Any CPU.Build.0 = Release|Any CPU
85 | {8926C6B9-213D-4569-A878-53204473E75E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
86 | {8926C6B9-213D-4569-A878-53204473E75E}.Debug|Any CPU.Build.0 = Debug|Any CPU
87 | {8926C6B9-213D-4569-A878-53204473E75E}.DebugWithSymbol|Any CPU.ActiveCfg = Debug|Any CPU
88 | {8926C6B9-213D-4569-A878-53204473E75E}.DebugWithSymbol|Any CPU.Build.0 = Debug|Any CPU
89 | {8926C6B9-213D-4569-A878-53204473E75E}.Release|Any CPU.ActiveCfg = Release|Any CPU
90 | {8926C6B9-213D-4569-A878-53204473E75E}.Release|Any CPU.Build.0 = Release|Any CPU
91 | {45D30D7D-271F-4833-8E80-09831F79F1E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
92 | {45D30D7D-271F-4833-8E80-09831F79F1E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
93 | {45D30D7D-271F-4833-8E80-09831F79F1E5}.DebugWithSymbol|Any CPU.ActiveCfg = Debug|Any CPU
94 | {45D30D7D-271F-4833-8E80-09831F79F1E5}.DebugWithSymbol|Any CPU.Build.0 = Debug|Any CPU
95 | {45D30D7D-271F-4833-8E80-09831F79F1E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
96 | {45D30D7D-271F-4833-8E80-09831F79F1E5}.Release|Any CPU.Build.0 = Release|Any CPU
97 | {0F6953CF-37F3-4759-AF46-A62ABB49D76C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
98 | {0F6953CF-37F3-4759-AF46-A62ABB49D76C}.Debug|Any CPU.Build.0 = Debug|Any CPU
99 | {0F6953CF-37F3-4759-AF46-A62ABB49D76C}.DebugWithSymbol|Any CPU.ActiveCfg = Debug|Any CPU
100 | {0F6953CF-37F3-4759-AF46-A62ABB49D76C}.DebugWithSymbol|Any CPU.Build.0 = Debug|Any CPU
101 | {0F6953CF-37F3-4759-AF46-A62ABB49D76C}.Release|Any CPU.ActiveCfg = Release|Any CPU
102 | {0F6953CF-37F3-4759-AF46-A62ABB49D76C}.Release|Any CPU.Build.0 = Release|Any CPU
103 | {228A0A82-EF20-459D-A9CD-564EC02A45E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
104 | {228A0A82-EF20-459D-A9CD-564EC02A45E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
105 | {228A0A82-EF20-459D-A9CD-564EC02A45E2}.DebugWithSymbol|Any CPU.ActiveCfg = Debug|Any CPU
106 | {228A0A82-EF20-459D-A9CD-564EC02A45E2}.DebugWithSymbol|Any CPU.Build.0 = Debug|Any CPU
107 | {228A0A82-EF20-459D-A9CD-564EC02A45E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
108 | {228A0A82-EF20-459D-A9CD-564EC02A45E2}.Release|Any CPU.Build.0 = Release|Any CPU
109 | {88B10D30-4A93-4BC0-9CF5-F813B40A6943}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
110 | {88B10D30-4A93-4BC0-9CF5-F813B40A6943}.Debug|Any CPU.Build.0 = Debug|Any CPU
111 | {88B10D30-4A93-4BC0-9CF5-F813B40A6943}.DebugWithSymbol|Any CPU.ActiveCfg = Debug|Any CPU
112 | {88B10D30-4A93-4BC0-9CF5-F813B40A6943}.DebugWithSymbol|Any CPU.Build.0 = Debug|Any CPU
113 | {88B10D30-4A93-4BC0-9CF5-F813B40A6943}.Release|Any CPU.ActiveCfg = Release|Any CPU
114 | {88B10D30-4A93-4BC0-9CF5-F813B40A6943}.Release|Any CPU.Build.0 = Release|Any CPU
115 | {50FC98FF-EAE1-478D-B9F9-846DA11372AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
116 | {50FC98FF-EAE1-478D-B9F9-846DA11372AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
117 | {50FC98FF-EAE1-478D-B9F9-846DA11372AD}.DebugWithSymbol|Any CPU.ActiveCfg = Debug|Any CPU
118 | {50FC98FF-EAE1-478D-B9F9-846DA11372AD}.DebugWithSymbol|Any CPU.Build.0 = Debug|Any CPU
119 | {50FC98FF-EAE1-478D-B9F9-846DA11372AD}.Release|Any CPU.ActiveCfg = Release|Any CPU
120 | {50FC98FF-EAE1-478D-B9F9-846DA11372AD}.Release|Any CPU.Build.0 = Release|Any CPU
121 | {43EAD90D-01D0-4468-BD44-86D20A88F947}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
122 | {43EAD90D-01D0-4468-BD44-86D20A88F947}.Debug|Any CPU.Build.0 = Debug|Any CPU
123 | {43EAD90D-01D0-4468-BD44-86D20A88F947}.DebugWithSymbol|Any CPU.ActiveCfg = Debug|Any CPU
124 | {43EAD90D-01D0-4468-BD44-86D20A88F947}.DebugWithSymbol|Any CPU.Build.0 = Debug|Any CPU
125 | {43EAD90D-01D0-4468-BD44-86D20A88F947}.Release|Any CPU.ActiveCfg = Release|Any CPU
126 | {43EAD90D-01D0-4468-BD44-86D20A88F947}.Release|Any CPU.Build.0 = Release|Any CPU
127 | EndGlobalSection
128 | GlobalSection(SolutionProperties) = preSolution
129 | HideSolutionNode = FALSE
130 | EndGlobalSection
131 | GlobalSection(NestedProjects) = preSolution
132 | {9AD83669-5DE8-44E5-9C12-BAD90FB93A23} = {1FE0C1A9-B34A-4B9A-8B13-9342D28B849E}
133 | {E36ADD7C-3E12-44D5-9A56-0B5C086EF755} = {1FE0C1A9-B34A-4B9A-8B13-9342D28B849E}
134 | {1FE0C1A9-B34A-4B9A-8B13-9342D28B849E} = {E36FC976-3345-4988-B710-C7F5DEAD2EF6}
135 | {A161FC5B-E3D9-4814-BFFB-90FD8AE1E158} = {F75FAB67-13B6-4A4D-8FD9-C30D4A7B648F}
136 | {9CF5C149-650A-42C4-A08E-0A066FE7721A} = {E36FC976-3345-4988-B710-C7F5DEAD2EF6}
137 | {79FBDE75-2C12-4684-ADCB-C8004D305373} = {9CF5C149-650A-42C4-A08E-0A066FE7721A}
138 | {7C6EAD80-D219-4792-98D7-247248918968} = {9CF5C149-650A-42C4-A08E-0A066FE7721A}
139 | {5CF6B6AA-635A-46A3-A0BC-A84294BB205E} = {F75FAB67-13B6-4A4D-8FD9-C30D4A7B648F}
140 | {8926C6B9-213D-4569-A878-53204473E75E} = {E36FC976-3345-4988-B710-C7F5DEAD2EF6}
141 | {45D30D7D-271F-4833-8E80-09831F79F1E5} = {F75FAB67-13B6-4A4D-8FD9-C30D4A7B648F}
142 | {0F6953CF-37F3-4759-AF46-A62ABB49D76C} = {9CF5C149-650A-42C4-A08E-0A066FE7721A}
143 | {228A0A82-EF20-459D-A9CD-564EC02A45E2} = {F75FAB67-13B6-4A4D-8FD9-C30D4A7B648F}
144 | {88B10D30-4A93-4BC0-9CF5-F813B40A6943} = {F75FAB67-13B6-4A4D-8FD9-C30D4A7B648F}
145 | {50FC98FF-EAE1-478D-B9F9-846DA11372AD} = {1E21D3A9-D00F-45AF-99EC-BF8123ACE33F}
146 | {43EAD90D-01D0-4468-BD44-86D20A88F947} = {F75FAB67-13B6-4A4D-8FD9-C30D4A7B648F}
147 | EndGlobalSection
148 | GlobalSection(ExtensibilityGlobals) = postSolution
149 | SolutionGuid = {5A9383CD-0E2F-46A6-8783-0315851AAD4C}
150 | EndGlobalSection
151 | EndGlobal
152 |
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.Mongo.TODO.Service/Microsoft.Solutions.CosmosDB.Mongo.TODO.Service.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net5.0
5 | Debug;Release
6 |
7 |
8 |
9 | TRACE;MONGO
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.Mongo.TODO.Service/Models/TODO.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT License.
3 |
4 | using System;
5 |
6 | namespace Microsoft.Solutions.CosmosDB.Mongo.TODO.Service.Models
7 | {
8 | public class ToDo : CosmosDBEntityBase
9 | {
10 | public string title { get; set; }
11 | public Status status { get; set; }
12 | public DateTime startDate { get; set; }
13 | public DateTime endDate { get; set; }
14 | public string notes { get; set; }
15 |
16 | private int _percentComplete;
17 |
18 | public int percentComplete
19 | {
20 | get { return _percentComplete; }
21 | set
22 | {
23 | if ((percentComplete < 0) || (percentComplete > 100))
24 | {
25 | throw new OverflowException("percent value should be between 0 to 100");
26 | }
27 | else
28 | {
29 | _percentComplete = percentComplete;
30 | }
31 | }
32 | }
33 | }
34 |
35 | public enum Status { New, InProcess, Done }
36 | }
37 |
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.Mongo.TODO.Service/TODOService.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT License.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Threading.Tasks;
7 | using Microsoft.Solutions.CosmosDB.Mongo.TODO.Service.Models;
8 |
9 | namespace Microsoft.Solutions.CosmosDB.Mongo.TODO.Service
10 | {
11 | public class TODOService : MongoEntntyCollectionBase
12 | {
13 | public TODOService(string DataConnectionString, string CollectionName) : base(DataConnectionString, CollectionName)
14 | {
15 |
16 | }
17 |
18 | public async Task Create(string title, Status status, int percentComplete, DateTime startDate, DateTime endDate, string notes)
19 | {
20 | return await this.EntityCollection.AddAsync(
21 | new ToDo()
22 | {
23 | title = title,
24 | status = status,
25 | percentComplete = percentComplete,
26 | startDate = startDate,
27 | endDate = endDate,
28 | notes = notes
29 | }
30 | );
31 | }
32 |
33 | public async Task Update(ToDo todo)
34 | {
35 | return await this.EntityCollection.SaveAsync(todo);
36 | }
37 |
38 | public async Task Delete(string id)
39 | {
40 | await this.EntityCollection.DeleteAsync(id);
41 | }
42 |
43 | public async Task Find(string id)
44 | {
45 | return await this.EntityCollection.GetAsync(id);
46 | }
47 |
48 | public async Task> Search(string notes)
49 | {
50 | return await this.EntityCollection.FindAllAsync(new GenericSpecification(x => x.notes.Contains(notes)));
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.Mongo.TODO.Tests/Microsoft.Solutions.CosmosDB.Mongo.TODO.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net5.0
5 |
6 | false
7 |
8 |
9 |
10 | TRACE;MONGO
11 | false
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.Mongo.TODO.Tests/TODOServiceTests.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT License.
3 |
4 | using Microsoft.Solutions.CosmosDB.Mongo.TODO.Service;
5 | using Microsoft.Solutions.CosmosDB.Mongo.TODO.Service.Models;
6 | using Microsoft.VisualStudio.TestTools.UnitTesting;
7 | using Newtonsoft.Json;
8 | using System;
9 | using System.Threading.Tasks;
10 |
11 | namespace Microsoft.Solutions.CosmosDB.Mongo.TODO.Tests
12 | {
13 | [TestClass()]
14 | public class TODOServiceTests
15 | {
16 | static TODOService todoService;
17 | static string mongoConnString = "{Put Your ConnectionString}";
18 | static string objectId;
19 |
20 | [TestInitialize]
21 | public void InitTest()
22 | {
23 | todoService = new TODOService(mongoConnString, "COSMOSDB-MONGO");
24 | }
25 |
26 |
27 | [TestMethod()]
28 | public async Task TEST01_CreateTODOTest()
29 | {
30 | var result = await todoService.Create("test title", Status.New, 0, DateTime.Today, DateTime.Today.AddDays(7), "bla bla");
31 | objectId = result.id;
32 | }
33 |
34 | [TestMethod()]
35 | public async Task TEST02_UpdateTODOTest()
36 | {
37 | var createdTodoObj = await todoService.Find(objectId);
38 | createdTodoObj.notes = "updated bla bla";
39 |
40 | await todoService.Update(createdTodoObj);
41 |
42 | }
43 |
44 | [TestMethod()]
45 | public async Task TEST03_SearchTODOTest()
46 | {
47 | var todos = await todoService.Search("updated");
48 |
49 | foreach (var todo in todos)
50 | {
51 | Console.WriteLine($"{todo.id} - {todo.status} - {todo.notes}");
52 | }
53 | }
54 |
55 | [TestMethod()]
56 | public async Task TEST04_RemoveTODOTest()
57 | {
58 | var createdTodoObj = await todoService.Find(objectId);
59 | Console.WriteLine($"{JsonConvert.SerializeObject(createdTodoObj)} will be removed");
60 | await todoService.Delete(objectId);
61 | }
62 |
63 | }
64 | }
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.SQL.ChangeFeed.Service/Dockerfile:
--------------------------------------------------------------------------------
1 | #See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
2 |
3 | FROM mcr.microsoft.com/dotnet/runtime:5.0 AS base
4 | WORKDIR /app
5 |
6 | FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
7 | WORKDIR /src
8 | COPY ["Sample/Microsoft.Solutions.CosmosDB.SQL.ChangeFeed.Service/Microsoft.Solutions.CosmosDB.SQL.ChangeFeed.Service.csproj", "Sample/Microsoft.Solutions.CosmosDB.SQL.ChangeFeed.Service/"]
9 | COPY ["libraries/Microsoft.Solutions.CosmosDB.SQL.ChangeFeed/Microsoft.Solutions.CosmosDB.SQL.ChangeFeed.csproj", "libraries/Microsoft.Solutions.CosmosDB.SQL.ChangeFeed/"]
10 | COPY ["libraries/Microsoft.Solutions.CosmosDB/Microsoft.Solutions.CosmosDB.csproj", "libraries/Microsoft.Solutions.CosmosDB/"]
11 | COPY ["libraries/Microsoft.Solutions.CosmosDB.SQL/Microsoft.Solutions.CosmosDB.SQL.csproj", "libraries/Microsoft.Solutions.CosmosDB.SQL/"]
12 | RUN dotnet restore "Sample/Microsoft.Solutions.CosmosDB.SQL.ChangeFeed.Service/Microsoft.Solutions.CosmosDB.SQL.ChangeFeed.Service.csproj"
13 | COPY . .
14 | WORKDIR "/src/Sample/Microsoft.Solutions.CosmosDB.SQL.ChangeFeed.Service"
15 | RUN dotnet build "Microsoft.Solutions.CosmosDB.SQL.ChangeFeed.Service.csproj" -c Release -o /app/build
16 |
17 | FROM build AS publish
18 | RUN dotnet publish "Microsoft.Solutions.CosmosDB.SQL.ChangeFeed.Service.csproj" -c Release -o /app/publish
19 |
20 | FROM base AS final
21 | WORKDIR /app
22 | COPY --from=publish /app/publish .
23 | ENTRYPOINT ["dotnet", "Microsoft.Solutions.CosmosDB.SQL.TODO.ChangeFeed.Service.dll"]
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.SQL.ChangeFeed.Service/Microsoft.Solutions.CosmosDB.SQL.ChangeFeed.Service.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net5.0
5 | dotnet-Microsoft.Solutions.CosmosDB.SQL.ChangeFeed.Service-C3808731-9407-4BE4-85FA-FA48ADFBF125
6 | Linux
7 | ..\..
8 | Microsoft.Solutions.CosmosDB.SQL.TODO.ChangeFeed.Service
9 | Microsoft.Solutions.CosmosDB.SQL.TODO.ChangeFeed.Service
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.SQL.ChangeFeed.Service/Models/TODO.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT License.
3 |
4 | using System;
5 |
6 | namespace Microsoft.Solutions.CosmosDB.SQL.ChangeFeed.Service.Models
7 | {
8 | public class ToDo : CosmosDBEntityBase
9 | {
10 | public string title { get; set; }
11 | public Status status { get; set; }
12 | public DateTime startDate { get; set; }
13 | public DateTime endDate { get; set; }
14 | public string notes { get; set; }
15 |
16 | private int _percentComplete;
17 |
18 | public int percentComplete
19 | {
20 | get { return _percentComplete; }
21 | set
22 | {
23 | if ((percentComplete < 0) || (percentComplete > 100))
24 | {
25 | throw new OverflowException("percent value should be between 0 to 100");
26 | }
27 | else
28 | {
29 | _percentComplete = percentComplete;
30 | }
31 | }
32 | }
33 | }
34 |
35 | public enum Status { New, InProcess, Done }
36 | }
37 |
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.SQL.ChangeFeed.Service/Program.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 | using Microsoft.Extensions.Hosting;
3 | using Microsoft.Solutions.CosmosDB.SQL.ChangeFeed.Service.Models;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Threading.Tasks;
8 |
9 | namespace Microsoft.Solutions.CosmosDB.SQL.TODO.ChangeFeed.Service
10 | {
11 | public class Program
12 | {
13 | public static void Main(string[] args)
14 | {
15 | CreateHostBuilder(args).Build().Run();
16 | }
17 |
18 | public static IHostBuilder CreateHostBuilder(string[] args) =>
19 | Host.CreateDefaultBuilder(args)
20 | .ConfigureServices((hostContext, services) =>
21 | {
22 | services.AddHostedService();
23 | });
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.SQL.ChangeFeed.Service/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "profiles": {
3 | "Microsoft.Solutions.CosmosDB.SQL.ChangeFeed.Service": {
4 | "commandName": "Project",
5 | "environmentVariables": {
6 | "DOTNET_ENVIRONMENT": "Development"
7 | },
8 | "dotnetRunMessages": "true"
9 | },
10 | "Docker": {
11 | "commandName": "Docker"
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.SQL.ChangeFeed.Service/Worker.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Configuration;
2 | using Microsoft.Solutions.CosmosDB.SQL.ChangeFeed;
3 | using Microsoft.Solutions.CosmosDB.SQL.ChangeFeed.Service.Models;
4 | using Newtonsoft.Json;
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Threading;
8 | using System.Threading.Tasks;
9 |
10 | namespace Microsoft.Solutions.CosmosDB.SQL.TODO.ChangeFeed.Service
11 | {
12 | public class Worker : Watcher
13 | {
14 | ///
15 | /// Passing configuration by ASPnet core Dependency Injection
16 | /// This Application sample shows how to detact changes for TODO collection by Microsoft.Solutions.CosmosDB.SQL.TODO.WebHost Demo App
17 | ///
18 | /// Check appsettings.json file definition
19 | public Worker(IConfiguration configuration) : base(configuration["Values:DBConnectionString"],
20 | configuration["Values:MonitoredDatabaseName"],
21 | configuration["Values:MonitoredContainerName"])
22 | {
23 | }
24 |
25 | protected override Task OnChangedFeedDataSets(IReadOnlyCollection changes, CancellationToken cancellationToken)
26 | {
27 | //put your business logics with changes
28 | foreach (var item in changes)
29 | {
30 | Console.WriteLine($"Detected operation for item with id {item.id} => {JsonConvert.SerializeObject(item)}");
31 | }
32 |
33 | return base.OnChangedFeedDataSets(changes, cancellationToken);
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.SQL.ChangeFeed.Service/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.SQL.ChangeFeed.Service/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | },
9 | "Values": {
10 | "DBConnectionString": "{Put Your ConnectionString}",
11 | "MonitoredDatabaseName": "COSMOS-SQLSDK",
12 | "MonitoredContainerName": "ToDos"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.SQL.SDK.TODO.Service.Tests/Microsoft.Solutions.CosmosDB.SQL.TODO.Service.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net5.0
5 |
6 | false
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.SQL.SDK.TODO.Service.Tests/TODOServiceTests.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT License.
3 |
4 | using Microsoft.VisualStudio.TestTools.UnitTesting;
5 | using System;
6 | using System.Threading.Tasks;
7 | using Microsoft.Solutions.CosmosDB.SQL.SDK.TODO.Service.Models;
8 |
9 | namespace Microsoft.Solutions.CosmosDB.SQL.SDK.TODO.Service.Tests
10 | {
11 | [TestClass()]
12 | public class TODOServiceTests
13 | {
14 | static TODOService todoService;
15 | static string connString = "{PUT YOUR COSMOS SQL Core API CONNECTION STRING}";
16 | static string objectId;
17 |
18 | [TestInitialize]
19 | public void InitTest()
20 | {
21 | todoService = new TODOService(connString, "COSMOS-SQLSDK", "CosmosToDo");
22 | }
23 |
24 |
25 | [TestMethod()]
26 | public async Task TEST01_CreateTODOTest()
27 | {
28 | var result = await todoService.Create("test title", Status.New, 0, DateTime.Today, DateTime.Today.AddDays(7), "bla bla");
29 | objectId = result.id;
30 | Console.WriteLine(objectId);
31 | }
32 |
33 | [TestMethod()]
34 | public async Task TEST02_UpdateTODOTest()
35 | {
36 | var createdTodoObj = await todoService.Find(objectId);
37 | createdTodoObj.notes = "updated bla bla";
38 |
39 | await todoService.Update(createdTodoObj);
40 |
41 | }
42 |
43 | [TestMethod()]
44 | public async Task TEST03_SearchTODOTest()
45 | {
46 | var todos = await todoService.Search("updated");
47 |
48 | foreach (var todo in todos)
49 | {
50 | Console.WriteLine($"{todo.id} - {todo.status} - {todo.notes}");
51 | }
52 | }
53 |
54 | [TestMethod()]
55 | public async Task TEST04_RemoveTODOTest()
56 | {
57 | var createdTodoObj = await todoService.Find(objectId);
58 | Console.WriteLine($"{createdTodoObj} will be removed");
59 | await todoService.Delete(objectId);
60 | }
61 | }
62 | }
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.SQL.SDK.TODO.Service/Microsoft.Solutions.CosmosDB.SQL.TODO.Service.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net5.0
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.SQL.SDK.TODO.Service/Models/TODO.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT License.
3 |
4 | using System;
5 |
6 | namespace Microsoft.Solutions.CosmosDB.SQL.SDK.TODO.Service.Models
7 | {
8 | public class ToDo : CosmosDBEntityBase
9 | {
10 | public string title { get; set; }
11 | public Status status { get; set; }
12 | public DateTime startDate { get; set; }
13 | public DateTime endDate { get; set; }
14 | public string notes { get; set; }
15 |
16 | private int _percentComplete;
17 |
18 | public int percentComplete
19 | {
20 | get { return _percentComplete; }
21 | set
22 | {
23 | if ((percentComplete < 0) || (percentComplete > 100))
24 | {
25 | throw new OverflowException("percent value should be between 0 to 100");
26 | }
27 | else
28 | {
29 | _percentComplete = percentComplete;
30 | }
31 | }
32 | }
33 | }
34 |
35 | public enum Status { New, InProcess, Done }
36 | }
37 |
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.SQL.SDK.TODO.Service/TODOService.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT License.
3 |
4 | using Microsoft.Solutions.CosmosDB.SQL.SDK.TODO.Service.Models;
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Threading.Tasks;
8 |
9 | namespace Microsoft.Solutions.CosmosDB.SQL.SDK.TODO.Service
10 | {
11 | public class TODOService : SQLEntityCollectionBase
12 | {
13 | public TODOService(string DataConnectionString, string CollectionName, string EntitySetName) : base(DataConnectionString, CollectionName, EntitySetName)
14 | {
15 | }
16 |
17 | public async Task Create(string title, Status status, int percentComplete, DateTime startDate, DateTime endDate, string notes)
18 | {
19 | return await this.EntityCollection.AddAsync(
20 | new ToDo()
21 | {
22 | title = title,
23 | status = status,
24 | percentComplete = percentComplete,
25 | startDate = startDate,
26 | endDate = endDate,
27 | notes = notes
28 | }
29 | );
30 | }
31 |
32 | public async Task Update(ToDo todo)
33 | {
34 | return await this.EntityCollection.SaveAsync(todo);
35 | }
36 |
37 | public async Task Delete(string id)
38 | {
39 | await this.EntityCollection.DeleteAsync(id);
40 | }
41 |
42 | public async Task Find(string id)
43 | {
44 | return await this.EntityCollection.GetAsync(id);
45 | }
46 |
47 | public async Task> Search(string notes)
48 | {
49 | return await this.EntityCollection.FindAllAsync(new GenericSpecification(x => x.notes.Contains(notes)));
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.WebHost/Controllers/ToDoController.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT License.
3 |
4 | using Microsoft.AspNetCore.Mvc;
5 | using Microsoft.Solutions.CosmosDB.SQL.SDK.TODO.Service.Models;
6 | using System.Collections.Generic;
7 | using System.Threading.Tasks;
8 |
9 | namespace Microsoft.Solutions.CosmosDB.TODO.WebHost.Controllers
10 | {
11 | [ApiController]
12 | [Route("[controller]")]
13 | public class ToDoController : ControllerBase
14 | {
15 | private IDataRepositoryProvider todoRepo;
16 |
17 | public ToDoController(IDataRepositoryProvider repo)
18 | {
19 | todoRepo = repo;
20 | }
21 |
22 | [HttpGet]
23 | public async Task> Get()
24 | {
25 | return await todoRepo.EntityCollection.GetAllAsync();
26 | }
27 |
28 | [HttpGet]
29 | [Route("FindNotes")]
30 | public async Task> FindNotes(string searchValue)
31 | {
32 | return await todoRepo.EntityCollection.FindAllAsync(new GenericSpecification(x => x.notes.Contains(searchValue)));
33 | }
34 |
35 | [HttpGet]
36 | [Route("FindTitle")]
37 | public async Task> FindTitle(string searchValue)
38 | {
39 | return await todoRepo.EntityCollection.FindAllAsync(new GenericSpecification(x => x.title.Contains(searchValue)));
40 | }
41 |
42 | [HttpPost]
43 | public async Task AddNew(ToDo todo)
44 | {
45 | return await todoRepo.EntityCollection.AddAsync(
46 | new ToDo()
47 | {
48 | title = todo.title,
49 | startDate = todo.startDate,
50 | endDate = todo.endDate,
51 | notes = todo.notes,
52 | percentComplete = todo.percentComplete,
53 | status = todo.status
54 | }
55 | );
56 | }
57 |
58 | [HttpDelete]
59 | public async Task Delete(string id)
60 | {
61 | await todoRepo.EntityCollection.DeleteAsync(id);
62 | }
63 |
64 | [HttpPut]
65 | public async Task Update(ToDo todo)
66 | {
67 | await todoRepo.EntityCollection.SaveAsync(todo);
68 | }
69 |
70 |
71 |
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.WebHost/Dockerfile:
--------------------------------------------------------------------------------
1 | #See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
2 |
3 | FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base
4 | WORKDIR /app
5 | EXPOSE 80
6 | EXPOSE 443
7 |
8 | FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
9 | WORKDIR /src
10 | COPY ["Sample/Microsoft.Solutions.CosmosDB.WebHost/Microsoft.Solutions.CosmosDB.TODO.WebHost.csproj", "Sample/Microsoft.Solutions.CosmosDB.WebHost/"]
11 | COPY ["Sample/Microsoft.Solutions.CosmosDB.SQL.SDK.TODO.Service/Microsoft.Solutions.CosmosDB.SQL.TODO.Service.csproj", "Sample/Microsoft.Solutions.CosmosDB.SQL.SDK.TODO.Service/"]
12 | COPY ["libraries/Microsoft.Solutions.CosmosDB/Microsoft.Solutions.CosmosDB.csproj", "libraries/Microsoft.Solutions.CosmosDB/"]
13 | COPY ["libraries/Microsoft.Solutions.CosmosDB.SQL/Microsoft.Solutions.CosmosDB.SQL.csproj", "libraries/Microsoft.Solutions.CosmosDB.SQL/"]
14 | RUN dotnet restore "Sample/Microsoft.Solutions.CosmosDB.WebHost/Microsoft.Solutions.CosmosDB.TODO.WebHost.csproj"
15 | COPY . .
16 | WORKDIR "/src/Sample/Microsoft.Solutions.CosmosDB.WebHost"
17 | RUN dotnet build "Microsoft.Solutions.CosmosDB.TODO.WebHost.csproj" -c Release -o /app/build
18 |
19 | FROM build AS publish
20 | RUN dotnet publish "Microsoft.Solutions.CosmosDB.TODO.WebHost.csproj" -c Release -o /app/publish
21 |
22 | FROM base AS final
23 | WORKDIR /app
24 | COPY --from=publish /app/publish .
25 | ENTRYPOINT ["dotnet", "Microsoft.Solutions.CosmosDB.TODO.WebHost.dll"]
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.WebHost/Microsoft.Solutions.CosmosDB.TODO.WebHost.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net5.0
5 | e0d84ef4-7119-4d28-931f-66d3d32289f1
6 | Linux
7 | ..\..
8 | Microsoft.Solutions.CosmosDB.TODO.WebHost.Program
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.WebHost/Program.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT License.
3 |
4 | using Microsoft.AspNetCore.Hosting;
5 | using Microsoft.Extensions.Hosting;
6 |
7 | namespace Microsoft.Solutions.CosmosDB.TODO.WebHost
8 | {
9 | public class Program
10 | {
11 | public static void Main(string[] args)
12 | {
13 | CreateHostBuilder(args).Build().Run();
14 | }
15 |
16 | public static IHostBuilder CreateHostBuilder(string[] args) =>
17 | Host.CreateDefaultBuilder(args)
18 | .ConfigureWebHostDefaults(webBuilder =>
19 | {
20 | webBuilder.UseStartup();
21 | });
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.WebHost/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "iisSettings": {
3 | "windowsAuthentication": false,
4 | "anonymousAuthentication": true,
5 | "iisExpress": {
6 | "applicationUrl": "http://localhost:55132",
7 | "sslPort": 44380
8 | }
9 | },
10 | "$schema": "http://json.schemastore.org/launchsettings.json",
11 | "profiles": {
12 | "IIS Express": {
13 | "commandName": "IISExpress",
14 | "launchBrowser": true,
15 | "launchUrl": "swagger",
16 | "environmentVariables": {
17 | "ASPNETCORE_ENVIRONMENT": "Development"
18 | }
19 | },
20 | "WebApplication1": {
21 | "commandName": "Project",
22 | "launchBrowser": true,
23 | "launchUrl": "swagger",
24 | "environmentVariables": {
25 | "ASPNETCORE_ENVIRONMENT": "Development"
26 | },
27 | "dotnetRunMessages": "true",
28 | "applicationUrl": "https://localhost:5001;http://localhost:5000"
29 | },
30 | "Docker": {
31 | "commandName": "Docker",
32 | "launchBrowser": true,
33 | "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger",
34 | "publishAllPorts": true,
35 | "useSSL": true
36 | }
37 | }
38 | }
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.WebHost/Startup.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT License.
3 |
4 | using Microsoft.AspNetCore.Builder;
5 | using Microsoft.AspNetCore.Hosting;
6 | using Microsoft.Extensions.Configuration;
7 | using Microsoft.Extensions.DependencyInjection;
8 | using Microsoft.Extensions.Hosting;
9 | using Microsoft.OpenApi.Models;
10 | using Microsoft.Solutions.CosmosDB.Security.ManagedIdentity;
11 | using Microsoft.Solutions.CosmosDB.SQL.SDK.TODO.Service;
12 | using Microsoft.Solutions.CosmosDB.SQL.SDK.TODO.Service.Models;
13 | using System.Threading.Tasks;
14 |
15 | namespace Microsoft.Solutions.CosmosDB.TODO.WebHost
16 | {
17 | public class Startup
18 | {
19 | public Startup(IConfiguration configuration)
20 | {
21 | Configuration = configuration;
22 | }
23 |
24 | public IConfiguration Configuration { get; }
25 |
26 | // This method gets called by the runtime. Use this method to add services to the container.
27 | public void ConfigureServices(IServiceCollection services)
28 | {
29 |
30 | services.AddControllers();
31 | services.AddCosmosHelper(Configuration);
32 | services.AddSwaggerGen(c =>
33 | {
34 | c.SwaggerDoc("v1", new OpenApiInfo { Title = "Contoso TODO Web API", Version = "v1" });
35 | });
36 | }
37 |
38 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
39 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
40 | {
41 | if (env.IsDevelopment())
42 | {
43 | app.UseDeveloperExceptionPage();
44 | app.UseSwagger();
45 | app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Contoso TODO Web API v1"));
46 | }
47 |
48 | app.UseHttpsRedirection();
49 |
50 | app.UseRouting();
51 |
52 | app.UseAuthorization();
53 |
54 | app.UseEndpoints(endpoints =>
55 | {
56 | endpoints.MapControllers();
57 | });
58 | }
59 | }
60 |
61 | static class CustomExtensionsMethods
62 | {
63 | public static IServiceCollection AddCosmosHelper(this IServiceCollection services, IConfiguration configuration)
64 | {
65 | services.AddTransient, TODOService>(x => { return new TODOService(ConnectionStringHelper.GetConnectionString(configuration).Result, "CosmosHandson", "ToDoSample"); });
66 |
67 | return services;
68 | }
69 | }
70 |
71 | static class ConnectionStringHelper
72 | {
73 | private static string _connectionString;
74 |
75 | public async static Task GetConnectionString(IConfiguration Configuration)
76 | {
77 | if (!string.IsNullOrEmpty(ConnectionStringHelper._connectionString)) return ConnectionStringHelper._connectionString;
78 |
79 | var objConnectionStrings = await ConnectionStringAccessor.Create(Configuration["App:SubscriptionId"],
80 | Configuration["App:ResourceGroupName"],
81 | Configuration["App:DatabaseAccountName"])
82 | .GetConnectionStringsAsync(Configuration["App:ManagedIdentityId"]);
83 | ConnectionStringHelper._connectionString = objConnectionStrings.PrimaryReadWriteKey;
84 |
85 | return ConnectionStringHelper._connectionString;
86 | }
87 | }
88 |
89 | }
90 |
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.WebHost/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.WebHost/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | },
9 | "AllowedHosts": "*",
10 | "App": {
11 | "SubscriptionId": "{Put Your Subscription Id}",
12 | "ResourceGroupName": "{Put Your Resourcegroup Name}",
13 | "ManagedIdentityId": "{Put Your Managed Identity Client Id}",
14 | "DatabaseAccountName": "{Put Your CosmosDB Account Name}"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.WebHost/azds.yaml:
--------------------------------------------------------------------------------
1 | kind: helm-release
2 | apiVersion: 1.1
3 | build:
4 | context: ..\..
5 | dockerfile: Dockerfile
6 | install:
7 | chart: charts/microsoftsolutionscosmosdbwebhost
8 | values:
9 | - values.dev.yaml?
10 | - secrets.dev.yaml?
11 | set:
12 | # Optionally, specify an array of imagePullSecrets. These secrets must be manually created in the namespace.
13 | # This will override the imagePullSecrets array in values.yaml file.
14 | # If the dockerfile specifies any private registry, the imagePullSecret for that registry must be added here.
15 | # ref: https://kubernetes.io/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod
16 | #
17 | # For example, the following uses credentials from secret "myRegistryKeySecretName".
18 | #
19 | # imagePullSecrets:
20 | # - name: myRegistryKeySecretName
21 | replicaCount: 1
22 | image:
23 | repository: microsoftsolutionscosmosdbwebhost
24 | tag: $(tag)
25 | pullPolicy: Never
26 | ingress:
27 | annotations:
28 | kubernetes.io/ingress.class: traefik-azds
29 | hosts:
30 | # This expands to form the service's public URL: [space.s.][rootSpace.]microsoftsolutionscosmosdbwebhost...azds.io
31 | # Customize the public URL by changing the 'microsoftsolutionscosmosdbwebhost' text between the $(rootSpacePrefix) and $(hostSuffix) tokens
32 | # For more information see https://aka.ms/devspaces/routing
33 | - $(spacePrefix)$(rootSpacePrefix)microsoftsolutionscosmosdbwebhost$(hostSuffix)
34 | configurations:
35 | develop:
36 | build:
37 | dockerfile: Dockerfile.develop
38 | useGitIgnore: true
39 | args:
40 | BUILD_CONFIGURATION: ${BUILD_CONFIGURATION:-Debug}
41 | container:
42 | sync:
43 | - "**/Pages/**"
44 | - "**/Views/**"
45 | - "**/wwwroot/**"
46 | - "!**/*.{sln,csproj}"
47 | command: [dotnet, run, --no-restore, --no-build, --no-launch-profile, -c, "${BUILD_CONFIGURATION:-Debug}"]
48 | iterate:
49 | processesToKill: [dotnet, vsdbg, Microsoft,Solutions.CosmosDB.TODO.WebHost]
50 | buildCommands:
51 | - [dotnet, build, --no-restore, -c, "${BUILD_CONFIGURATION:-Debug}"]
52 |
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.WebHost/charts/microsoftsolutionscosmosdbwebhost/.helmignore:
--------------------------------------------------------------------------------
1 | # Patterns to ignore when building packages.
2 | # This supports shell glob matching, relative path matching, and
3 | # negation (prefixed with !). Only one pattern per line.
4 | .DS_Store
5 | # Common VCS dirs
6 | .git/
7 | .gitignore
8 | .bzr/
9 | .bzrignore
10 | .hg/
11 | .hgignore
12 | .svn/
13 | # Common backup files
14 | *.swp
15 | *.bak
16 | *.tmp
17 | *~
18 | # Various IDEs
19 | .project
20 | .idea/
21 | *.tmproj
22 |
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.WebHost/charts/microsoftsolutionscosmosdbwebhost/Chart.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | appVersion: "1.0"
3 | description: A Helm chart for Kubernetes
4 | name: microsoftsolutionscosmosdbwebhost
5 | version: 0.1.0
6 |
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.WebHost/charts/microsoftsolutionscosmosdbwebhost/templates/NOTES.txt:
--------------------------------------------------------------------------------
1 | 1. Get the application URL by running these commands:
2 | {{- if .Values.ingress.enabled }}
3 | {{- range .Values.ingress.hosts }}
4 | http{{ if $.Values.ingress.tls }}s{{ end }}://{{ . }}{{ $.Values.ingress.path }}
5 | {{- end }}
6 | {{- else if contains "NodePort" .Values.service.type }}
7 | export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "microsoftsolutionscosmosdbwebhost.fullname" . }})
8 | export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
9 | echo http://$NODE_IP:$NODE_PORT
10 | {{- else if contains "LoadBalancer" .Values.service.type }}
11 | NOTE: It may take a few minutes for the LoadBalancer IP to be available.
12 | You can watch the status of by running 'kubectl get svc -w {{ template "microsoftsolutionscosmosdbwebhost.fullname" . }}'
13 | export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "microsoftsolutionscosmosdbwebhost.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
14 | echo http://$SERVICE_IP:{{ .Values.service.port }}
15 | {{- else if contains "ClusterIP" .Values.service.type }}
16 | export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "microsoftsolutionscosmosdbwebhost.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
17 | echo "Visit http://127.0.0.1:8080 to use your application"
18 | kubectl port-forward $POD_NAME 8080:80
19 | {{- end }}
20 |
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.WebHost/charts/microsoftsolutionscosmosdbwebhost/templates/_helpers.tpl:
--------------------------------------------------------------------------------
1 | {{/* vim: set filetype=mustache: */}}
2 | {{/*
3 | Expand the name of the chart.
4 | */}}
5 | {{- define "microsoftsolutionscosmosdbwebhost.name" -}}
6 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
7 | {{- end -}}
8 |
9 | {{/*
10 | Create a default fully qualified app name.
11 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
12 | If release name contains chart name it will be used as a full name.
13 | */}}
14 | {{- define "microsoftsolutionscosmosdbwebhost.fullname" -}}
15 | {{- if .Values.fullnameOverride -}}
16 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
17 | {{- else -}}
18 | {{- $name := default .Chart.Name .Values.nameOverride -}}
19 | {{- if contains $name .Release.Name -}}
20 | {{- .Release.Name | trunc 63 | trimSuffix "-" -}}
21 | {{- else -}}
22 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
23 | {{- end -}}
24 | {{- end -}}
25 | {{- end -}}
26 |
27 | {{/*
28 | Create chart name and version as used by the chart label.
29 | */}}
30 | {{- define "microsoftsolutionscosmosdbwebhost.chart" -}}
31 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
32 | {{- end -}}
33 |
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.WebHost/charts/microsoftsolutionscosmosdbwebhost/templates/deployment.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | name: {{ template "microsoftsolutionscosmosdbwebhost.fullname" . }}
5 | labels:
6 | app: {{ template "microsoftsolutionscosmosdbwebhost.name" . }}
7 | chart: {{ template "microsoftsolutionscosmosdbwebhost.chart" . }}
8 | draft: {{ .Values.draft | default "draft-app" }}
9 | release: {{ .Release.Name }}
10 | heritage: {{ .Release.Service }}
11 | spec:
12 | revisionHistoryLimit: 0
13 | replicas: {{ .Values.replicaCount }}
14 | selector:
15 | matchLabels:
16 | app: {{ template "microsoftsolutionscosmosdbwebhost.name" . }}
17 | release: {{ .Release.Name }}
18 | template:
19 | metadata:
20 | labels:
21 | app: {{ template "microsoftsolutionscosmosdbwebhost.name" . }}
22 | draft: {{ .Values.draft | default "draft-app" }}
23 | release: {{ .Release.Name }}
24 | annotations:
25 | buildID: {{ .Values.buildID | default "" | quote }}
26 | spec:
27 | containers:
28 | - name: {{ .Chart.Name }}
29 | image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
30 | imagePullPolicy: {{ .Values.image.pullPolicy }}
31 | ports:
32 | - name: http
33 | containerPort: {{ .Values.deployment.containerPort }}
34 | protocol: TCP
35 | {{- if .Values.probes.enabled }}
36 | livenessProbe:
37 | httpGet:
38 | path: /
39 | port: http
40 | readinessProbe:
41 | httpGet:
42 | path: /
43 | port: http
44 | {{- end }}
45 | env:
46 | {{- $root := . }}
47 | {{- range $ref, $values := .Values.secrets }}
48 | {{- range $key, $value := $values }}
49 | - name: {{ $ref }}_{{ $key }}
50 | valueFrom:
51 | secretKeyRef:
52 | name: {{ template "microsoftsolutionscosmosdbwebhost.fullname" $root }}-{{ $ref | lower }}
53 | key: {{ $key }}
54 | {{- end }}
55 | {{- end }}
56 | resources:
57 | {{ toYaml .Values.resources | indent 12 }}
58 | {{- with .Values.imagePullSecrets }}
59 | imagePullSecrets:
60 | {{ toYaml . | indent 8 }}
61 | {{- end }}
62 | {{- with .Values.nodeSelector }}
63 | nodeSelector:
64 | {{ toYaml . | indent 8 }}
65 | {{- end }}
66 | {{- with .Values.affinity }}
67 | affinity:
68 | {{ toYaml . | indent 8 }}
69 | {{- end }}
70 | {{- with .Values.tolerations }}
71 | tolerations:
72 | {{ toYaml . | indent 8 }}
73 | {{- end }}
74 |
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.WebHost/charts/microsoftsolutionscosmosdbwebhost/templates/ingress.yaml:
--------------------------------------------------------------------------------
1 | {{- if .Values.ingress.enabled -}}
2 | {{- $fullName := include "microsoftsolutionscosmosdbwebhost.fullname" . -}}
3 | {{- $servicePort := .Values.service.port -}}
4 | {{- $ingressPath := .Values.ingress.path -}}
5 | {{- if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
6 | apiVersion: networking.k8s.io/v1beta1
7 | {{- else -}}
8 | apiVersion: extensions/v1beta1
9 | {{- end }}
10 | kind: Ingress
11 | metadata:
12 | name: {{ $fullName }}
13 | labels:
14 | app: {{ template "microsoftsolutionscosmosdbwebhost.name" . }}
15 | chart: {{ template "microsoftsolutionscosmosdbwebhost.chart" . }}
16 | release: {{ .Release.Name }}
17 | heritage: {{ .Release.Service }}
18 | {{- with .Values.ingress.annotations }}
19 | annotations:
20 | {{ toYaml . | indent 4 }}
21 | {{- end }}
22 | spec:
23 | {{- if .Values.ingress.tls }}
24 | tls:
25 | {{- range .Values.ingress.tls }}
26 | - hosts:
27 | {{- range .hosts }}
28 | - {{ . }}
29 | {{- end }}
30 | secretName: {{ .secretName }}
31 | {{- end }}
32 | {{- end }}
33 | rules:
34 | {{- range .Values.ingress.hosts }}
35 | - host: {{ . }}
36 | http:
37 | paths:
38 | - path: {{ $ingressPath }}
39 | backend:
40 | serviceName: {{ $fullName }}
41 | servicePort: http
42 | {{- end }}
43 | {{- end }}
44 |
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.WebHost/charts/microsoftsolutionscosmosdbwebhost/templates/secrets.yaml:
--------------------------------------------------------------------------------
1 | {{- $root := . }}
2 | {{- range $name, $values := .Values.secrets }}
3 | apiVersion: v1
4 | kind: Secret
5 | metadata:
6 | name: {{ template "microsoftsolutionscosmosdbwebhost.fullname" $root }}-{{ $name | lower }}
7 | data:
8 | {{- range $key, $value := $values }}
9 | {{ $key }}: {{ $value | b64enc }}
10 | {{- end }}
11 | ---
12 | {{- end }}
13 |
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.WebHost/charts/microsoftsolutionscosmosdbwebhost/templates/service.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Service
3 | metadata:
4 | name: {{ template "microsoftsolutionscosmosdbwebhost.fullname" . }}
5 | labels:
6 | app: {{ template "microsoftsolutionscosmosdbwebhost.name" . }}
7 | chart: {{ template "microsoftsolutionscosmosdbwebhost.chart" . }}
8 | release: {{ .Release.Name }}
9 | heritage: {{ .Release.Service }}
10 | spec:
11 | type: {{ .Values.service.type }}
12 | ports:
13 | - port: {{ .Values.service.port }}
14 | targetPort: http
15 | protocol: TCP
16 | name: http
17 | selector:
18 | app: {{ template "microsoftsolutionscosmosdbwebhost.name" . }}
19 | release: {{ .Release.Name }}
20 |
--------------------------------------------------------------------------------
/src/Sample/Microsoft.Solutions.CosmosDB.WebHost/charts/microsoftsolutionscosmosdbwebhost/values.yaml:
--------------------------------------------------------------------------------
1 | # Default values for microsoftsolutionscosmosdbwebhost.
2 | # This is a YAML-formatted file.
3 | # Declare variables to be passed into your templates.
4 | fullnameOverride: microsoftsolutionscosmosdbwebhost
5 | replicaCount: 1
6 | image:
7 | repository: microsoftsolutionscosmosdbwebhost
8 | tag: stable
9 | pullPolicy: IfNotPresent
10 | imagePullSecrets: []
11 | # Optionally specify an array of imagePullSecrets.
12 | # Secrets must be manually created in the namespace.
13 | # ref: https://kubernetes.io/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod
14 | #
15 | # This uses credentials from secret "myRegistryKeySecretName".
16 | # - name: myRegistryKeySecretName
17 | service:
18 | type: ClusterIP
19 | port: 80
20 |
21 | deployment:
22 | containerPort: 80
23 |
24 | probes:
25 | enabled: false
26 |
27 | ingress:
28 | enabled: false
29 | annotations: {}
30 | # kubernetes.io/tls-acme: "true"
31 | path: /
32 | # hosts:
33 | # - chart-example.local
34 | tls: []
35 | # - secretName: chart-example-tls
36 | # hosts:
37 | # - chart-example.local
38 | secrets: {}
39 | # Optionally specify a set of secret objects whose values
40 | # will be injected as environment variables by default.
41 | # You should add this section to a file like secrets.yaml
42 | # that is explicitly NOT committed to source code control
43 | # and then include it as part of your helm install step.
44 | # ref: https://kubernetes.io/docs/concepts/configuration/secret/
45 | #
46 | # This creates a secret "mysecret" and injects "mypassword"
47 | # as the environment variable mysecret_mypassword=password.
48 | # mysecret:
49 | # mypassword: password
50 | resources: {}
51 | # We usually recommend not to specify default resources and to leave this as a conscious
52 | # choice for the user. This also increases chances charts run on environments with little
53 | # resources, such as Minikube. If you do want to specify resources, uncomment the following
54 | # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
55 | # limits:
56 | # cpu: 100m
57 | # memory: 128Mi
58 | # requests:
59 | # cpu: 100m
60 | # memory: 128Mi
61 | nodeSelector: {}
62 |
63 | tolerations: []
64 |
65 | affinity: {}
--------------------------------------------------------------------------------
/src/Utils/Microsoft.Solutions.HTTP/HttpClient.cs:
--------------------------------------------------------------------------------
1 | using Flurl.Http;
2 | using Polly;
3 | using Polly.Retry;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Net;
8 | using System.Text;
9 | using System.Threading.Tasks;
10 |
11 | namespace Microsoft.Solutions.HTTP
12 | {
13 | public class HttpClient
14 | {
15 | static HttpClient()
16 | {
17 | policy = BuildRetryPolicy();
18 | }
19 |
20 | static AsyncRetryPolicy policy;
21 |
22 | public static string ServiceBaseUrl = "";
23 |
24 | public static async Task GetJsonAsync(string url, string bearerToken = "", object headers = null)
25 | {
26 | return await policy.ExecuteAsync(
27 | () => url
28 | .WithHeaders(new { Accept = "application/json" })
29 | .WithOAuthBearerToken(bearerToken)
30 | .GetJsonAsync()
31 | );
32 | }
33 |
34 | public static async Task PostJsonAsync(string url, object data, string bearerToken = "")
35 | {
36 | return await policy.ExecuteAsync(async () => await url
37 | .WithHeaders(new { Accept = "application/json" })
38 | .WithOAuthBearerToken(bearerToken)
39 | .PostJsonAsync(data)
40 | .ReceiveJson());
41 |
42 | }
43 |
44 | public static async Task PostJsonAsyncWithHeaders(string url, object data, string bearerToken = "", object headers = null)
45 | {
46 | return await policy.ExecuteAsync(async () => await url
47 | .WithHeaders(headers)
48 | .WithOAuthBearerToken(bearerToken)
49 | .PostJsonAsync(data)
50 | .ReceiveJson());
51 |
52 | }
53 |
54 |
55 | private static bool IsTransientError(FlurlHttpException exception)
56 | {
57 | int[] httpStatusCodesWorthRetrying =
58 | {
59 | (int)HttpStatusCode.RequestTimeout, // 408
60 | (int)HttpStatusCode.BadGateway, // 502
61 | (int)HttpStatusCode.ServiceUnavailable, // 503
62 | (int)HttpStatusCode.GatewayTimeout // 504
63 | };
64 |
65 | return exception.StatusCode.HasValue && httpStatusCodesWorthRetrying.Contains(exception.StatusCode.Value);
66 | }
67 |
68 | private static AsyncRetryPolicy BuildRetryPolicy()
69 | {
70 | var retryPolicy = Policy
71 | .Handle(IsTransientError)
72 | .WaitAndRetryAsync(3, retryAttempt =>
73 | {
74 | var nextAttemptIn = TimeSpan.FromSeconds(Math.Pow(2, retryAttempt));
75 | Console.WriteLine($"Retry attempt {retryAttempt} to make request. Next try on {nextAttemptIn.TotalSeconds} seconds.");
76 | return nextAttemptIn;
77 | });
78 |
79 | return retryPolicy;
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/Utils/Microsoft.Solutions.HTTP/Microsoft.Solutions.HTTP.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net5.0
5 | EAE.Solutions.HTTP
6 | True
7 | EAE.Solutions.HTTP
8 | 0.7.3
9 | Microsoft Solutions
10 | Microsoft Coporation
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/libraries/Microsoft.Solutions.CosmosDB.Security.ManagedIdentity/ConnectionStringAccessor.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Azure.Identity;
3 | using Microsoft.Solutions.HTTP;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 |
7 | namespace Microsoft.Solutions.CosmosDB.Security.ManagedIdentity
8 | {
9 | public class ConnectionStringAccessor
10 | {
11 | public ConnectionStringAccessor()
12 | {
13 | }
14 |
15 | public static ConnectionStringAccessor Create(string SubscriptionId, string ResourceGroupName, string CosmosDBAccountName)
16 | {
17 | return new ConnectionStringAccessor(SubscriptionId, ResourceGroupName, CosmosDBAccountName);
18 | }
19 |
20 | private string listConnectionStringAPIUrl = string.Empty;
21 | private DefaultAzureCredential azureCredential = null;
22 |
23 | private ConnectionStringAccessor(string SubscriptionId, string ResourceGroupName, string CosmosDBAccountName)
24 | {
25 | // Setup the List Connection Strings API to get the Azure Cosmos DB keys.
26 | listConnectionStringAPIUrl = @$"https://management.azure.com/subscriptions/{SubscriptionId}/resourceGroups/{ResourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/{CosmosDBAccountName}/listConnectionStrings?api-version=2021-04-15";
27 | Console.WriteLine(listConnectionStringAPIUrl);
28 | }
29 |
30 |
31 | ///
32 | /// Retrive Cosmos DB Connection string with ManagedIdentity
33 | ///
34 | /// The ManagedIdentity should have Cosmos DB Account Reader Role
35 | /// CosmosConnectionStrings (ReadWrite / ReadOnly)
36 | public async Task GetConnectionStringsAsync(string ManagedIdentityClientId)
37 | {
38 | azureCredential = new DefaultAzureCredential(
39 | new DefaultAzureCredentialOptions()
40 | {
41 | ManagedIdentityClientId = ManagedIdentityClientId
42 | });
43 |
44 | var AccessToken = await azureCredential.GetTokenAsync(
45 | new Azure.Core.TokenRequestContext(
46 | new[] { "https://management.azure.com//.default" }));
47 |
48 | var result = await HttpClient.PostJsonAsync(listConnectionStringAPIUrl, string.Empty, AccessToken.Token);
49 |
50 | return new CosmosConnectionStrings()
51 | {
52 | PrimaryReadWriteKey = result.connectionStrings[0].connectionString,
53 | SecondaryReadWriteKey = result.connectionStrings[1].connectionString,
54 | PrimaryReadOnlyKey = result.connectionStrings[2].connectionString,
55 | SecondaryReadOnlyKey = result.connectionStrings[3].connectionString
56 | };
57 | }
58 | }
59 |
60 | public class CosmosConnectionStrings
61 | {
62 | public string PrimaryReadWriteKey { get; set; }
63 | public string SecondaryReadWriteKey { get; set; }
64 | public string PrimaryReadOnlyKey { get; set; }
65 | public string SecondaryReadOnlyKey { get; set; }
66 | }
67 |
68 | internal class ConnectionStrings
69 | {
70 | public ConnectionString[] connectionStrings { get; set; }
71 | }
72 |
73 | internal class ConnectionString
74 | {
75 | public string connectionString { get; set; }
76 | public string description { get; set; }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/libraries/Microsoft.Solutions.CosmosDB.Security.ManagedIdentity/Microsoft.Solutions.CosmosDB.Security.ManagedIdentity.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net5.0
5 | EAE.Solutions.CosmosDB.Security.ManagedIdentity
6 | True
7 | 0.7.3
8 | Microsoft Solutions
9 | Microsoft Corporation
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------