Introduction
In the
previous post, we demonstrated how to use DotVVM to create CRUD application with Azure Cosmos DB as your data store.
In this post, we will demonstrate how to do the same with Cloud Firestore by Google.
What is Cloud Firestore?
Cloud Firestore is a flexible, scalable database for mobile, web, and server development from Firebase and Google Cloud Platform. It keeps your data in-sync across client apps through realtime listeners and offers offline support for mobile and web apps.
To learn more about Cloud Firebase, visit
here.
Install the DotVVM extension
To know more about the DotVVM extension visit its page on visual studio marketplace: https://marketplace.visualstudio.com/items?itemName=TomasHerceg.DotVVM-VSExtension2019
Now you are ready to start coding with the DotVVM framework. DotVVM extension installs the DotVVM sample project, which we will use to demonstrate how it is easy to connect to the Cloud Firestore database from a DotVVM application.
Create A Cloud Firestore Project
To use the cloud Firestore as your database, you need to create a project on Firestore.
- Go here and log in with your Google account or create a new one.
- Click on Add Project
- Enter dotvvm as the project name.
- In the next step, Disable Google Analytics for this project. It is recommended to enable it for a real project.
- Click on Create Project. it will take one or two mins to create your project. When it is ready, click on continue.
- From the left navigation panel, open Database then click on Create database
- In the popup window, select Start in test mode then click next.
- Select the location of your database(you can keep the default selection), then Click Done.
- Congratulations, your Cloud Firestore database is created and ready!
To be able to connect to your Firestore database from your application(server) you need to set the GOOGLE_APPLICATION_CREDENTIALS environment variable to point to the JSON service account key file.
To set up your service account, go
here and follow the instructions.
DotVVM Web Application
In the
previous post, you can find the complete steps for creating the DotVVM web application. In this post, we focus on code changes required to connect to Firestore database.
- Uninstall the entity framework SQL Server related NuGet package using the following commands in the Package Manager Console pane in Visual Studio, as we are going to connect to our Cloud Firestore database, not the SQL Server database.
- uninstall-package Microsoft.EntityFrameworkCore.SqlServer
-
- uninstall-package Microsoft.EntityFrameworkCore
- Install Google.Cloud.Firestore nuget package. This package is required to run CRUD operations against your Firestore database from your web application.
- install-package Google.Cloud.Firestore
- Open appsettings.json file and remove the connection string. keeping it will not harm but we need our code to be clean.
- Delete DAL/StudentDbContext.cs file.
- Open Startup.cs file and delete the following lines
- services.AddEntityFrameworkSqlServer()
- .AddDbContext<Studentdbcontext>(options =>
- {
- options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
- });
- Open DAL/Entities/Student.cs file and add the following using statement:
- using Google.Cloud.Firestore;
- Decorate the Student class with [FirestoreData] attribute and each property with [FirestoreProperty] attribute. Also, change the type of EnrollmentDate property to Timestamp instead of DateTime. The complete code of Student class will be like below:
- [FirestoreData]
- public class Student
- {
- [FirestoreProperty]
- public int Id { get; set; }
-
- [FirestoreProperty]
- public string FirstName { get; set; }
-
- [FirestoreProperty]
- public string LastName { get; set; }
-
- [FirestoreProperty]
- public string About { get; set; }
-
- [FirestoreProperty]
- public Timestamp EnrollmentDate { get; set; }
- }
Those attributes are required and used to serialize/deserialize your entities from and to json objects. Timestamp is the Firestore datatype used to represent date/time values.
- Open Services/StudentService.cs file and add the following private properties to StudentService class, where the project is the name of your Firestore project and collection is the name of your database collection where you will insert/retrieve records.
- private const string project = "dotvvm";
- private const string collection = "students";
- Replace the GetAllStudentsAsync method with the following:
- public async Task<List<StudentListModel>> GetAllStudentsAsync()
- {
- var studentsList = new List<Student>();
- FirestoreDb db = FirestoreDb.Create(Project);
- Query allStudentsQuery = db.Collection(Collection);
- QuerySnapshot allStudentsQuerySnapshot = await allStudentsQuery.GetSnapshotAsync();
- foreach (DocumentSnapshot documentSnapshot in allStudentsQuerySnapshot.Documents)
- {
- studentsList.Add(documentSnapshot.ConvertTo<Student>());
- }
- return studentsList.Select(s => new StudentListModel
- {
- Id = s.Id,
- FirstName = s.FirstName,
- LastName = s.LastName
- }
- ).ToList();
- }
- Replace the GetStudentByIdAsync method with the following:
- public async Task<StudentListModel> GetStudentByIdAsync()
- {
- FirestoreDb db = FirestoreDb.Create(Project);
- Query docRef = db.Collection(Collection).WhereEqualTo("Id", studentId).Limit(1);
- QuerySnapshot snapshot = await docRef.GetSnapshotAsync();
- if (snapshot.Count > 0)
- {
- Student student = snapshot.ElementAt(0).ConvertTo<Student>();
- return new StudentDetailModel()
- {
- About = student.About,
- EnrollmentDate = student.EnrollmentDate.ToDateTime(),
- FirstName = student.FirstName,
- Id = student.Id,
- LastName = student.LastName
- };
- }
- else
- {
- return null;
- }
- }
- Replace the UpdateStudentAsync method with the following:
- public async Task UpdateStudentAsync(StudentDetailModel student)
- {
- FirestoreDb db = FirestoreDb.Create(Project);
- Query docRef = db.Collection(Collection).WhereEqualTo("Id", student.Id).Limit(1);
- QuerySnapshot snapshot = await docRef.GetSnapshotAsync();
- if (snapshot.Count > 0)
- {
- DocumentReference studentRef = db.Collection(Collection).Document(snapshot.ElementAt(0).Id);
- Dictionary<string, object> updates = new Dictionary<string, object>
- {
- { nameof(student.About), student.About},
- { nameof(student.EnrollmentDate), Timestamp.FromDateTime(student.EnrollmentDate.ToUniversalTime())},
- { nameof(student.FirstName), student.FirstName},
- { nameof(student.LastName), student.LastName}
- };
- await studentRef.UpdateAsync(updates);
- }
- }
- Replace the InsertStudentAsync method with the following:
- public async Task InsertStudentAsync(StudentDetailModel student)
- {
- var entity = new Student()
- {
- Id = new Random().Next(1, int.MaxValue),
- FirstName = student.FirstName,
- LastName = student.LastName,
- About = student.About,
-
- EnrollmentDate = Timestamp.FromDateTime(student.EnrollmentDate.ToUniversalTime())
- };
- FirestoreDb db = FirestoreDb.Create(Project);
- var Id = Guid.NewGuid().ToString();
- DocumentReference docRef = db.Collection(Collection).Document(Id);
- await docRef.SetAsync(entity);
- }
- Replace the DeleteStudentAsync method with the following
- public async Task DeleteStudentAsync(int studentId)
- {
- FirestoreDb db = FirestoreDb.Create(Project);
- Query docRef = db.Collection(Collection).WhereEqualTo("Id", studentId).Limit(1);
- QuerySnapshot snapshot = await docRef.GetSnapshotAsync();
- if (snapshot.Count > 0)
- {
- DocumentReference studentRef = db.Collection(Collection).Document(snapshot.ElementAt(0).Id);
- await studentRef.DeleteAsync();
- }
- }
- Run your application. If there is no error, you will see the following page in your browser:
- Click on New Item, fill the form, then click on Add
- Congratulations, you added your student to students Firestore collection!
- Go to your Firestore database, it should look like the following:
Notice that Firestore is created a student collection and is inserted your student entity as a JSON document. Also, notice how it represents the EnrollmentDate value as a timestamp.
Summary
In this article, we demonstrated how to create a sample DotVVM web application, Cloud Firestore database, and perform CRUD operations as we used to do with the SQL Server database or any other relational database. We have done changes in the sample project code to twist it from using Entity Framework Code First approach (SQL Server) to use Google Cloud FireStore .NET SDK.
You can find the complete source code on
GitHub