Welcome to the twenty-first episode of my course “Becoming a software developer” in which we will use MongoDB which is a NoSQL database for storing the data of our application.
All of the materials including videos and sample projects can be downloaded from here.
The source code repository is being hosted on GitHub.
Scope
- MongoDB
Abstract
MongoDB
This is one of the most popular NoSQL databases in the world. Beware that NoSQL is just a catchy buzzword – there are many different NoSQL databases with totally unique behavior and destination. Basically, whenever you hear NoSQL, you should think about data storage where you can put the data in a so-called collection that does not require any particular schema and is very flexible. Quite often JSON is used as the primary data type for storing the documents. Opposite to the SQL database, usually, NoSQL databases do not handle transactions and reference keys. On the other hand, it’s quite simple to map even 1:1 class to the document stored within such database which makes them a very interesting choice as the primary data storage type for the variety of applications. To connect to the database, you can use Robomongo which is a free GUI client.
In order to start with MongoDB and .NET Core, it is required to install MongoDB.Driver. Once completed, we can create custom MongoSettings, configure the IoC module and implement the actual repository for the users:
1 2 3 4 5 |
public class MongoSettings { public string ConnectionString { get; set; } public string Database { get; set; } } |
1 2 3 4 |
"mongo": { "connectionString": "mongodb://localhost:27017", "database": "Passenger" } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
public class MongoModule : Autofac.Module { protected override void Load(ContainerBuilder builder) { builder.Register((c,p) => { var settings = c.Resolve<MongoSettings>(); return new MongoClient(settings.ConnectionString); }).SingleInstance(); builder.Register((c,p) => { var client = c.Resolve<MongoClient>(); var settings = c.Resolve<MongoSettings>(); var database = client.GetDatabase(settings.Database); return database; }).As<IMongoDatabase>(); var assembly = typeof(RepositoryModule) .GetTypeInfo() .Assembly; builder.RegisterAssemblyTypes(assembly) .Where(x => x.IsAssignableTo<IMongoRepository>()) .AsImplementedInterfaces() .InstancePerLifetimeScope(); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
public class UserRepository : IUserRepository, IMongoRepository { private readonly IMongoDatabase _database; public UserRepository(IMongoDatabase database) { _database = database; } public async Task<User> GetAsync(Guid id) => await Users.AsQueryable().FirstOrDefaultAsync(x => x.Id == id); public async Task<User> GetAsync(string email) => await Users.AsQueryable().FirstOrDefaultAsync(x => x.Email == email); public async Task<IEnumerable<User>> GetAllAsync() => await Users.AsQueryable().ToListAsync(); public async Task AddAsync(User user) => await Users.InsertOneAsync(user); public async Task RemoveAsync(Guid id) => await Users.DeleteOneAsync(x => x.Id == id); public async Task UpdateAsync(User user) => await Users.ReplaceOneAsync(x => x.Id == user.Id, user); private IMongoCollection<User> Users => _database.GetCollection<User>("Users"); } |
Before we start using our brand new Mongo repository, let’s create so-called conventions and initialize them in a Startup class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
public static class MongoConfigurator { private static bool _initialized; public static void Initialize() { if(_initialized) { return; } _initialized = true; RegisterConventions(); } private static void RegisterConventions() { ConventionRegistry.Register("PassengerConventions", new MongoCovention(), x => true); } private class MongoCovention : IConventionPack { public IEnumerable<IConvention> Conventions => new List<IConvention> { new IgnoreExtraElementsConvention(true), new EnumRepresentationConvention(BsonType.String), new CamelCaseElementNameConvention() }; } } |
Eventually, we can secure the database by adding user to it and then fix the connection string property within the application settings:
1 2 3 4 5 6 7 8 9 |
use Passenger db.createUser({ user: "root", pwd: "secret", roles: [{ role: "dbOwner", db: "Passenger" }] }) |
1 2 3 4 |
"mongo": { "connectionString": "mongodb://root:secret@localhost:27017/Passenger", "database": "Passenger" } |
Next
In the next episode, we will use the SQL Server and Entity Framework Core to store the data in a typical SQL Server database.
Pingback: Dew Drop - June 15, 2017 (#2501) - Morning Dew
When will be the next episode ?
Hopefully, it will be recorded in the next few days.
你好!
hi, in these articles, you add services with Autofac by RegisterModule. And In “.NET Core Microservices” , you do these just with extension methods by AddSingleton or AddScoped. What’s the difference and which one is recommended?
Hi, under the hood you will achieve the same, the question is do you need a more advanced IoC container such as Autofac for your project. If that’s the case, go for this one.
Hi, now in the .net core 2.0, running “.NET Core Microservices” ‘s code directly would cause an exception when it calls “app.ApplicationServices.GetService()…” in the Configure() method. And i heard init database in the Configure() is not recommended now. So I have 2 questions. 1, How to get services in the Configure() in .net core 2.0? 2, How to init database with standard way in .net core 2.0?
thank you for sharing information