├── .dockerignore ├── .gitignore ├── Dockerfile ├── MongoDB.GenericRepository.sln ├── MongoDB.GenericRepository ├── Context │ └── MongoContext.cs ├── Controllers │ └── ProductController.cs ├── Interfaces │ ├── IMongoContext.cs │ ├── IProductRepository.cs │ ├── IRepository.cs │ └── IUnitOfWork.cs ├── Model │ └── Product.cs ├── MongoDB.GenericRepository.csproj ├── Persistence │ ├── MongoDbPersistence.cs │ └── ProductMap.cs ├── Program.cs ├── Properties │ └── launchSettings.json ├── Repository │ ├── BaseRepository.cs │ └── ProductRepository.cs ├── Startup.cs ├── UoW │ └── UnitOfWork.cs ├── ViewModel │ └── ProductViewModel.cs ├── appsettings.Development.json └── appsettings.json ├── README.MD └── docker-compose.yml /.dockerignore: -------------------------------------------------------------------------------- 1 | .dockerignore 2 | .env 3 | .git 4 | .gitignore 5 | .vs 6 | .vscode 7 | */bin 8 | */obj 9 | **/.toolstarget -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | [Xx]64/ 19 | [Xx]86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Dd]ist/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | 85 | # Visual Studio profiler 86 | *.psess 87 | *.vsp 88 | *.vspx 89 | *.sap 90 | 91 | # TFS 2012 Local Workspace 92 | $tf/ 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | *.DotSettings.user 101 | 102 | # JustCode is a .NET coding add-in 103 | .JustCode 104 | 105 | # TeamCity is a build add-in 106 | _TeamCity* 107 | 108 | # DotCover is a Code Coverage Tool 109 | *.dotCover 110 | 111 | # NCrunch 112 | _NCrunch_* 113 | .*crunch*.local.xml 114 | nCrunchTemp_* 115 | 116 | # MightyMoose 117 | *.mm.* 118 | AutoTest.Net/ 119 | 120 | # Web workbench (sass) 121 | .sass-cache/ 122 | 123 | # Installshield output folder 124 | [Ee]xpress/ 125 | 126 | # DocProject is a documentation generator add-in 127 | DocProject/buildhelp/ 128 | DocProject/Help/*.HxT 129 | DocProject/Help/*.HxC 130 | DocProject/Help/*.hhc 131 | DocProject/Help/*.hhk 132 | DocProject/Help/*.hhp 133 | DocProject/Help/Html2 134 | DocProject/Help/html 135 | 136 | # Click-Once directory 137 | publish/ 138 | 139 | # Publish Web Output 140 | *.[Pp]ublish.xml 141 | *.azurePubxml 142 | 143 | # TODO: Un-comment the next line if you do not want to checkin 144 | # your web deploy settings because they may include unencrypted 145 | # passwords 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # NuGet Packages 150 | *.nupkg 151 | # The packages folder can be ignored because of Package Restore 152 | **/packages/* 153 | # except build/, which is used as an MSBuild target. 154 | !**/packages/build/ 155 | # Uncomment if necessary however generally it will be regenerated when needed 156 | #!**/packages/repositories.config 157 | # NuGet v3's project.json files produces more ignoreable files 158 | *.nuget.props 159 | *.nuget.targets 160 | 161 | # Microsoft Azure Build Output 162 | csx/ 163 | *.build.csdef 164 | 165 | # Microsoft Azure Emulator 166 | ecf/ 167 | rcf/ 168 | 169 | # Windows Store app package directory 170 | AppPackages/ 171 | BundleArtifacts/ 172 | 173 | # Visual Studio cache files 174 | # files ending in .cache can be ignored 175 | *.[Cc]ache 176 | # but keep track of directories ending in .cache 177 | !*.[Cc]ache/ 178 | 179 | # Others 180 | ClientBin/ 181 | [Ss]tyle[Cc]op.* 182 | ~$* 183 | *~ 184 | *.dbmdl 185 | *.dbproj.schemaview 186 | *.pfx 187 | *.publishsettings 188 | node_modules/ 189 | orleans.codegen.cs 190 | 191 | # RIA/Silverlight projects 192 | Generated_Code/ 193 | 194 | # Backup & report files from converting an old project file 195 | # to a newer Visual Studio version. Backup files are not needed, 196 | # because we have git ;-) 197 | _UpgradeReport_Files/ 198 | Backup*/ 199 | UpgradeLog*.XML 200 | UpgradeLog*.htm 201 | 202 | # SQL Server files 203 | *.mdf 204 | *.ldf 205 | 206 | # Business Intelligence projects 207 | *.rdl.data 208 | *.bim.layout 209 | *.bim_*.settings 210 | 211 | # Microsoft Fakes 212 | FakesAssemblies/ 213 | 214 | # GhostDoc plugin setting file 215 | *.GhostDoc.xml 216 | 217 | # Node.js Tools for Visual Studio 218 | .ntvs_analysis.dat 219 | 220 | # Visual Studio 6 build log 221 | *.plg 222 | 223 | # Visual Studio 6 workspace options file 224 | *.opt 225 | 226 | # Visual Studio LightSwitch build output 227 | **/*.HTMLClient/GeneratedArtifacts 228 | **/*.DesktopClient/GeneratedArtifacts 229 | **/*.DesktopClient/ModelManifest.xml 230 | **/*.Server/GeneratedArtifacts 231 | **/*.Server/ModelManifest.xml 232 | _Pvt_Extensions 233 | 234 | # LightSwitch generated files 235 | GeneratedArtifacts/ 236 | ModelManifest.xml 237 | 238 | # Paket dependency manager 239 | .paket/paket.exe 240 | 241 | # FAKE - F# Make 242 | .fake/ 243 | 244 | # Sphinx 245 | *.opt 246 | docs/_build 247 | docs/.vscode -------------------------------------------------------------------------------- /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/core/aspnet:3.1-buster-slim AS base 4 | WORKDIR /app 5 | EXPOSE 80 6 | EXPOSE 443 7 | 8 | FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build 9 | WORKDIR /src 10 | COPY ["MongoDB.GenericRepository/MongoDB.GenericRepository.csproj", "MongoDB.GenericRepository/"] 11 | RUN dotnet restore "MongoDB.GenericRepository/MongoDB.GenericRepository.csproj" 12 | COPY . . 13 | WORKDIR "/src/MongoDB.GenericRepository" 14 | RUN dotnet build "MongoDB.GenericRepository.csproj" -c Release -o /app/build 15 | 16 | FROM build AS publish 17 | RUN dotnet publish "MongoDB.GenericRepository.csproj" -c Release -o /app/publish 18 | 19 | FROM base AS final 20 | WORKDIR /app 21 | COPY --from=publish /app/publish . 22 | ENTRYPOINT ["dotnet", "MongoDB.GenericRepository.dll"] -------------------------------------------------------------------------------- /MongoDB.GenericRepository.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28010.2026 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MongoDB.GenericRepository", "MongoDB.GenericRepository\MongoDB.GenericRepository.csproj", "{86BDE810-8CE3-4E05-A936-868F43AB2E90}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {86BDE810-8CE3-4E05-A936-868F43AB2E90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {86BDE810-8CE3-4E05-A936-868F43AB2E90}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {86BDE810-8CE3-4E05-A936-868F43AB2E90}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {86BDE810-8CE3-4E05-A936-868F43AB2E90}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {3E502A91-4597-4A07-9722-1F46AE8B4042} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /MongoDB.GenericRepository/Context/MongoContext.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using MongoDB.Driver; 3 | using MongoDB.GenericRepository.Interfaces; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Threading.Tasks; 8 | 9 | namespace MongoDB.GenericRepository.Context 10 | { 11 | public class MongoContext : IMongoContext 12 | { 13 | private IMongoDatabase Database { get; set; } 14 | public IClientSessionHandle Session { get; set; } 15 | public MongoClient MongoClient { get; set; } 16 | private readonly List> _commands; 17 | private readonly IConfiguration _configuration; 18 | 19 | public MongoContext(IConfiguration configuration) 20 | { 21 | _configuration = configuration; 22 | 23 | // Every command will be stored and it'll be processed at SaveChanges 24 | _commands = new List>(); 25 | } 26 | 27 | public async Task SaveChanges() 28 | { 29 | ConfigureMongo(); 30 | 31 | using (Session = await MongoClient.StartSessionAsync()) 32 | { 33 | Session.StartTransaction(); 34 | 35 | var commandTasks = _commands.Select(c => c()); 36 | 37 | await Task.WhenAll(commandTasks); 38 | 39 | await Session.CommitTransactionAsync(); 40 | } 41 | 42 | return _commands.Count; 43 | } 44 | 45 | private void ConfigureMongo() 46 | { 47 | if (MongoClient != null) 48 | { 49 | return; 50 | } 51 | 52 | // Configure mongo (You can inject the config, just to simplify) 53 | MongoClient = new MongoClient(_configuration["MongoSettings:Connection"]); 54 | 55 | Database = MongoClient.GetDatabase(_configuration["MongoSettings:DatabaseName"]); 56 | } 57 | 58 | public IMongoCollection GetCollection(string name) 59 | { 60 | ConfigureMongo(); 61 | 62 | return Database.GetCollection(name); 63 | } 64 | 65 | public void Dispose() 66 | { 67 | Session?.Dispose(); 68 | GC.SuppressFinalize(this); 69 | } 70 | 71 | public void AddCommand(Func func) 72 | { 73 | _commands.Add(func); 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /MongoDB.GenericRepository/Controllers/ProductController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using MongoDB.GenericRepository.Interfaces; 3 | using MongoDB.GenericRepository.Model; 4 | using MongoDB.GenericRepository.ViewModel; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Threading.Tasks; 8 | 9 | namespace MongoDB.GenericRepository.Controllers 10 | { 11 | [Route("[controller]")] 12 | [ApiController] 13 | public class ProductController : ControllerBase 14 | { 15 | private readonly IProductRepository _productRepository; 16 | private readonly IUnitOfWork _uow; 17 | 18 | public ProductController(IProductRepository productRepository, IUnitOfWork uow) 19 | { 20 | _productRepository = productRepository; 21 | _uow = uow; 22 | } 23 | 24 | [HttpGet] 25 | public async Task>> Get() 26 | { 27 | var products = await _productRepository.GetAll(); 28 | 29 | return Ok(products); 30 | } 31 | 32 | [HttpGet("{id}")] 33 | public async Task> Get(Guid id) 34 | { 35 | var product = await _productRepository.GetById(id); 36 | 37 | return Ok(product); 38 | } 39 | 40 | [HttpPost, Route("PostSimulatingError")] 41 | public IActionResult PostSimulatingError([FromBody] ProductViewModel value) 42 | { 43 | var product = new Product(value.Description); 44 | _productRepository.Add(product); 45 | 46 | // The product will not be added 47 | return BadRequest(); 48 | } 49 | 50 | [HttpPost] 51 | public async Task> Post([FromBody] ProductViewModel value) 52 | { 53 | var product = new Product(value.Description); 54 | _productRepository.Add(product); 55 | 56 | // it will be null 57 | var testProduct = await _productRepository.GetById(product.Id); 58 | 59 | // If everything is ok then: 60 | await _uow.Commit(); 61 | 62 | // The product will be added only after commit 63 | testProduct = await _productRepository.GetById(product.Id); 64 | 65 | return Ok(testProduct); 66 | } 67 | 68 | [HttpPut("{id}")] 69 | public async Task> Put(Guid id, [FromBody] ProductViewModel value) 70 | { 71 | var product = new Product(id, value.Description); 72 | 73 | _productRepository.Update(product); 74 | 75 | await _uow.Commit(); 76 | 77 | return Ok(await _productRepository.GetById(id)); 78 | } 79 | 80 | [HttpDelete("{id}")] 81 | public async Task Delete(Guid id) 82 | { 83 | _productRepository.Remove(id); 84 | 85 | // it won't be null 86 | var testProduct = await _productRepository.GetById(id); 87 | 88 | // If everything is ok then: 89 | await _uow.Commit(); 90 | 91 | // not it must by null 92 | testProduct = await _productRepository.GetById(id); 93 | 94 | return Ok(); 95 | } 96 | } 97 | } -------------------------------------------------------------------------------- /MongoDB.GenericRepository/Interfaces/IMongoContext.cs: -------------------------------------------------------------------------------- 1 | using MongoDB.Driver; 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace MongoDB.GenericRepository.Interfaces 6 | { 7 | public interface IMongoContext : IDisposable 8 | { 9 | void AddCommand(Func func); 10 | Task SaveChanges(); 11 | IMongoCollection GetCollection(string name); 12 | } 13 | } -------------------------------------------------------------------------------- /MongoDB.GenericRepository/Interfaces/IProductRepository.cs: -------------------------------------------------------------------------------- 1 | using MongoDB.GenericRepository.Model; 2 | 3 | namespace MongoDB.GenericRepository.Interfaces 4 | { 5 | public interface IProductRepository : IRepository 6 | { 7 | } 8 | } -------------------------------------------------------------------------------- /MongoDB.GenericRepository/Interfaces/IRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | 5 | namespace MongoDB.GenericRepository.Interfaces 6 | { 7 | public interface IRepository : IDisposable where TEntity : class 8 | { 9 | void Add(TEntity obj); 10 | Task GetById(Guid id); 11 | Task> GetAll(); 12 | void Update(TEntity obj); 13 | void Remove(Guid id); 14 | } 15 | } -------------------------------------------------------------------------------- /MongoDB.GenericRepository/Interfaces/IUnitOfWork.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace MongoDB.GenericRepository.Interfaces 5 | { 6 | public interface IUnitOfWork : IDisposable 7 | { 8 | Task Commit(); 9 | } 10 | } -------------------------------------------------------------------------------- /MongoDB.GenericRepository/Model/Product.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MongoDB.GenericRepository.Model 4 | { 5 | public class Product 6 | { 7 | public Product(string description) 8 | { 9 | Description = description; 10 | Id = Guid.NewGuid(); 11 | } 12 | 13 | public Product(Guid id, string description) 14 | { 15 | Id = id; 16 | Description = description; 17 | } 18 | 19 | public Guid Id { get; private set; } 20 | public string Description { get; private set; } 21 | } 22 | } -------------------------------------------------------------------------------- /MongoDB.GenericRepository/MongoDB.GenericRepository.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1 5 | InProcess 6 | Linux 7 | 3ea642bd-6e7a-4df2-aa87-d3ee9b381e84 8 | Linux 9 | 1.1.0.0 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /MongoDB.GenericRepository/Persistence/MongoDbPersistence.cs: -------------------------------------------------------------------------------- 1 | using MongoDB.Bson; 2 | using MongoDB.Bson.Serialization.Conventions; 3 | 4 | namespace MongoDB.GenericRepository.Persistence 5 | { 6 | public static class MongoDbPersistence 7 | { 8 | public static void Configure() 9 | { 10 | ProductMap.Configure(); 11 | 12 | BsonDefaults.GuidRepresentation = GuidRepresentation.CSharpLegacy; 13 | //BsonSerializer.RegisterSerializer(new GuidSerializer(GuidRepresentation.CSharpLegacy)); 14 | 15 | // Conventions 16 | var pack = new ConventionPack 17 | { 18 | new IgnoreExtraElementsConvention(true), 19 | new IgnoreIfDefaultConvention(true) 20 | }; 21 | ConventionRegistry.Register("My Solution Conventions", pack, t => true); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /MongoDB.GenericRepository/Persistence/ProductMap.cs: -------------------------------------------------------------------------------- 1 | using MongoDB.Bson.Serialization; 2 | using MongoDB.GenericRepository.Model; 3 | 4 | namespace MongoDB.GenericRepository.Persistence 5 | { 6 | public class ProductMap 7 | { 8 | public static void Configure() 9 | { 10 | BsonClassMap.RegisterClassMap(map => 11 | { 12 | map.AutoMap(); 13 | map.SetIgnoreExtraElements(true); 14 | map.MapIdMember(x => x.Id); 15 | map.MapMember(x => x.Description).SetIsRequired(true); 16 | }); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /MongoDB.GenericRepository/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using Microsoft.Extensions.Hosting; 3 | using Microsoft.Extensions.Logging; 4 | 5 | namespace MongoDB.GenericRepository 6 | { 7 | public class Program 8 | { 9 | public static void Main(string[] args) 10 | { 11 | CreateHostBuilder(args).Build().Run(); 12 | } 13 | 14 | public static IHostBuilder CreateHostBuilder(string[] args) => 15 | Host.CreateDefaultBuilder(args) 16 | .ConfigureLogging(log => 17 | { 18 | log.ClearProviders(); 19 | }) 20 | .ConfigureWebHostDefaults(webBuilder => 21 | { 22 | webBuilder.UseStartup(); 23 | }); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /MongoDB.GenericRepository/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:56522", 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 | "MongoDB.GenericRepository": { 21 | "commandName": "Project", 22 | "launchBrowser": true, 23 | "launchUrl": "swagger", 24 | "environmentVariables": { 25 | "ASPNETCORE_ENVIRONMENT": "Development" 26 | }, 27 | "applicationUrl": "https://localhost:5001;http://localhost:5000" 28 | }, 29 | "Docker": { 30 | "commandName": "Docker", 31 | "launchBrowser": true, 32 | "launchUrl": "{Scheme}://localhost:{ServicePort}/swagger" 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /MongoDB.GenericRepository/Repository/BaseRepository.cs: -------------------------------------------------------------------------------- 1 | using MongoDB.Driver; 2 | using MongoDB.GenericRepository.Interfaces; 3 | using ServiceStack; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Threading.Tasks; 7 | 8 | namespace MongoDB.GenericRepository.Repository 9 | { 10 | public abstract class BaseRepository : IRepository where TEntity : class 11 | { 12 | protected readonly IMongoContext Context; 13 | protected IMongoCollection DbSet; 14 | 15 | protected BaseRepository(IMongoContext context) 16 | { 17 | Context = context; 18 | 19 | DbSet = Context.GetCollection(typeof(TEntity).Name); 20 | } 21 | 22 | public virtual void Add(TEntity obj) 23 | { 24 | Context.AddCommand(() => DbSet.InsertOneAsync(obj)); 25 | } 26 | 27 | public virtual async Task GetById(Guid id) 28 | { 29 | var data = await DbSet.FindAsync(Builders.Filter.Eq("_id", id)); 30 | return data.SingleOrDefault(); 31 | } 32 | 33 | public virtual async Task> GetAll() 34 | { 35 | var all = await DbSet.FindAsync(Builders.Filter.Empty); 36 | return all.ToList(); 37 | } 38 | 39 | public virtual void Update(TEntity obj) 40 | { 41 | Context.AddCommand(() => DbSet.ReplaceOneAsync(Builders.Filter.Eq("_id", obj.GetId()), obj)); 42 | } 43 | 44 | public virtual void Remove(Guid id) 45 | { 46 | Context.AddCommand(() => DbSet.DeleteOneAsync(Builders.Filter.Eq("_id", id))); 47 | } 48 | 49 | public void Dispose() 50 | { 51 | Context?.Dispose(); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /MongoDB.GenericRepository/Repository/ProductRepository.cs: -------------------------------------------------------------------------------- 1 | using MongoDB.GenericRepository.Interfaces; 2 | using MongoDB.GenericRepository.Model; 3 | 4 | namespace MongoDB.GenericRepository.Repository 5 | { 6 | public class ProductRepository : BaseRepository, IProductRepository 7 | { 8 | public ProductRepository(IMongoContext context) : base(context) 9 | { 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /MongoDB.GenericRepository/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.AspNetCore.Mvc; 4 | using Microsoft.Extensions.Configuration; 5 | using Microsoft.Extensions.DependencyInjection; 6 | using Microsoft.Extensions.Hosting; 7 | using Microsoft.OpenApi.Models; 8 | using MongoDB.GenericRepository.Context; 9 | using MongoDB.GenericRepository.Interfaces; 10 | using MongoDB.GenericRepository.Persistence; 11 | using MongoDB.GenericRepository.Repository; 12 | using MongoDB.GenericRepository.UoW; 13 | using System; 14 | 15 | namespace MongoDB.GenericRepository 16 | { 17 | public class Startup 18 | { 19 | public IConfiguration Configuration { get; } 20 | 21 | public Startup(IConfiguration configuration) 22 | { 23 | Configuration = configuration; 24 | } 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 | services.AddControllers() 30 | .SetCompatibilityVersion(CompatibilityVersion.Version_3_0) 31 | .AddJsonOptions(opt => 32 | { 33 | var serializerOptions = opt.JsonSerializerOptions; 34 | serializerOptions.IgnoreNullValues = true; 35 | serializerOptions.IgnoreReadOnlyProperties = false; 36 | serializerOptions.WriteIndented = true; 37 | }); 38 | 39 | // Configure the persistence in another layer 40 | MongoDbPersistence.Configure(); 41 | 42 | services.AddSwaggerGen(s => 43 | { 44 | s.SwaggerDoc("v1", new OpenApiInfo 45 | { 46 | Version = "v1", 47 | Title = "MongoDB Repository Pattern and Unit of Work - Example", 48 | Description = "Swagger surface", 49 | Contact = new OpenApiContact 50 | { 51 | Name = "Bruno Brito", 52 | Email = "bhdebrito@gmail.com", 53 | Url = new Uri("http://www.brunobrito.net.br") 54 | }, 55 | License = new OpenApiLicense 56 | { 57 | Name = "MIT", 58 | Url = new Uri("https://github.com/brunohbrito/MongoDB-RepositoryUoWPatterns/blob/master/LICENSE") 59 | } 60 | }); 61 | }); 62 | 63 | RegisterServices(services); 64 | } 65 | 66 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 67 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 68 | { 69 | if (env.IsDevelopment()) 70 | { 71 | app.UseDeveloperExceptionPage(); 72 | } 73 | else 74 | { 75 | // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. 76 | app.UseHsts(); 77 | } 78 | 79 | app.UseHttpsRedirection(); 80 | 81 | app.UseRouting(); 82 | 83 | app.UseEndpoints(endpoints => 84 | { 85 | endpoints.MapControllers(); 86 | }); 87 | 88 | app.UseSwagger(c => 89 | { 90 | c.RouteTemplate = "swagger/{documentName}/swagger.json"; 91 | }); 92 | 93 | app.UseSwaggerUI(s => 94 | { 95 | s.SwaggerEndpoint("/swagger/v1/swagger.json", "Repository Pattern and Unit of Work API v1.0"); 96 | }); 97 | } 98 | 99 | private void RegisterServices(IServiceCollection services) 100 | { 101 | services.AddScoped(); 102 | services.AddScoped(); 103 | services.AddScoped(); 104 | } 105 | } 106 | } -------------------------------------------------------------------------------- /MongoDB.GenericRepository/UoW/UnitOfWork.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using MongoDB.GenericRepository.Interfaces; 3 | 4 | namespace MongoDB.GenericRepository.UoW 5 | { 6 | public class UnitOfWork : IUnitOfWork 7 | { 8 | private readonly IMongoContext _context; 9 | 10 | public UnitOfWork(IMongoContext context) 11 | { 12 | _context = context; 13 | } 14 | 15 | public async Task Commit() 16 | { 17 | var changeAmount = await _context.SaveChanges(); 18 | 19 | return changeAmount > 0; 20 | } 21 | 22 | public void Dispose() 23 | { 24 | _context.Dispose(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /MongoDB.GenericRepository/ViewModel/ProductViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace MongoDB.GenericRepository.ViewModel 2 | { 3 | public class ProductViewModel 4 | { 5 | public string Description { get; set; } 6 | public bool ShouldCommit { get; set; } = true; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /MongoDB.GenericRepository/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /MongoDB.GenericRepository/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Warning" 5 | } 6 | }, 7 | "AllowedHosts": "*", 8 | "MongoSettings": { 9 | "Connection": "mongodb://root:password123@localhost:27017", 10 | "DatabaseName": "Products" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | # ASP.NET Core - MongoDB Repository & Unit of Work Pattern 2 | 3 | 4 | Example App - This demo shows how to simple implement repository and unit of work patterns for MongoDB .Net driver. 5 | 6 | * **Server Side**: ASP.NET Core 7 | 8 | Pre reqs 9 | 10 | * Net.Core 3.1 11 | 12 | Techs: 13 | 14 | * ASP.NET Core 15 | * Swagger 16 | * ServiceStack.Core 17 | 18 | # How to run 19 | 20 | 1. Download code 21 | * Open folder 22 | * Open a terminal 23 | * docker-compose up --build 24 | 25 | 26 | More about on [ASP.NET Core - MongoDB Repository Pattern & Unit Of Work](https://www.brunobrito.net.br/aspnet-core-mongodb-unit-of-work/) - Portuguese only 27 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | # Use root/example as user/password credentials 2 | version: '3.8' 3 | 4 | services: 5 | 6 | generic-repo-uow: 7 | image: "generic-repo-uow" 8 | build: 9 | context: . 10 | dockerfile: Dockerfile 11 | ports: 12 | - "5005:5005" 13 | links: 14 | - mongodb-primary 15 | depends_on: 16 | - mongodb-primary 17 | environment: 18 | MONGOCONNECTION: "mongodb://root:password123@mongodb-primary:27017" 19 | DATABASENAME: "Products" 20 | ASPNETCORE_ENVIRONMENT: "Development" 21 | ASPNETCORE_URLS: http://+:5005 22 | 23 | mongodb-primary: 24 | image: 'bitnami/mongodb:latest' 25 | ports: 26 | - "27017:27017" 27 | environment: 28 | - MONGODB_ADVERTISED_HOSTNAME=mongodb-primary 29 | - MONGODB_REPLICA_SET_MODE=primary 30 | - MONGODB_ROOT_PASSWORD=password123 31 | - MONGODB_REPLICA_SET_KEY=replicasetkey123 32 | 33 | # volumes: 34 | # - 'mongodb_master_data:/bitnami' 35 | 36 | mongodb-secondary: 37 | image: 'bitnami/mongodb:latest' 38 | depends_on: 39 | - mongodb-primary 40 | environment: 41 | - MONGODB_ADVERTISED_HOSTNAME=mongodb-secondary 42 | - MONGODB_REPLICA_SET_MODE=secondary 43 | - MONGODB_INITIAL_PRIMARY_HOST=mongodb-primary 44 | - MONGODB_INITIAL_PRIMARY_PORT_NUMBER=27017 45 | - MONGODB_INITIAL_PRIMARY_ROOT_PASSWORD=password123 46 | - MONGODB_REPLICA_SET_KEY=replicasetkey123 47 | 48 | mongodb-arbiter: 49 | image: 'bitnami/mongodb:latest' 50 | depends_on: 51 | - mongodb-primary 52 | environment: 53 | - MONGODB_ADVERTISED_HOSTNAME=mongodb-arbiter 54 | - MONGODB_REPLICA_SET_MODE=arbiter 55 | - MONGODB_INITIAL_PRIMARY_HOST=mongodb-primary 56 | - MONGODB_INITIAL_PRIMARY_PORT_NUMBER=27017 57 | - MONGODB_INITIAL_PRIMARY_ROOT_PASSWORD=password123 58 | - MONGODB_REPLICA_SET_KEY=replicasetkey123 59 | 60 | # volumes: 61 | # mongodb_master_data: 62 | # driver: local --------------------------------------------------------------------------------