CRUD using gRPC, EF Core, and ASP.NET Core (Part - 1)

If you have read about the
new features of ASP.NET core
3.0, you are probably aware that it supports gRPC, a framework for building
services using Remote Procedure Call (RPC). I won't go into the dry information
about what gRPC is and how it can help you solve software problems in this
article. This multipart article creates a simple yet complete example that
performs CRUD operations on the Employees table of Northwind database. As you
develop this example you will get chance to familiarize yourself with the basics
of gRPC as implemented in .NET Core 3.0.
Let's get going.
Begin by creating a new Visual Studio project based on gRPC project template.

Once the project gets created your Solution Explorer should look similar to
this:

Notice the Ptotos folder that contains a .proto file. Rename the default fine
to EmployeeCRUD.proto. This file contains instructions of Protocol Buffer
language. The primary purpose of this file is to define the structure of a
service you wish to create. Structure of a service includes its methods, method
signatures, and types needed by the service.
At the top of EmployeeCRUD.proto file write (or modify) these lines:
syntax = "proto3";
package Northwind;
option csharp_namespace = "GrpcService1";
The first line tells that this file uses proto3 syntax (there is also
proto2). So, simply put it's the protocol buffer language version that this file
is using. The next two lines control the C# namespaces once this file is
compiled. I won't go into the details of package and csharp_namespace option
here but you can read more in the
documentation.
Next, you need to define the structure of your service. In this case you want
to create a service that performs CRUD operations on the Employees table. Here
is the structure of EmployeeCRUD service that we will be using for this example.
service EmployeeCRUD {
rpc SelectAll (Empty) returns (Employees);
rpc SelectByID (EmployeeFilter) returns (Employee);
rpc Insert (Employee) returns (Empty);
rpc Update (Employee) returns (Empty);
rpc Delete (EmployeeFilter) returns (Empty);
}
The above code defines structure for a service called EmployeeCRUD. There are
five "rpc" methods - SelectAll(), SelectByID(), Insert(), Update(), and
Delete(). Each method accepts a message and returns a message. These messages
are types that you have to define in the .proto file. For example, SelectAll()
method accepts a message of type Empty and returns a message of type Employees.
As the name suggests Empty message type doesn't pass anything to the method and
looks like this:
message Empty {
}
You can give any name of your choice to the message type. Here, we are using
Empty as the name.
The SelectAll() method returns a list of Employee objects in the form of
Employees type. So, there are two messages types to be defined - Employee and
Employees. They are shown below:
message Employee {
int32 employeeID = 1;
string firstName = 2;
string lastName = 3;
}
message Employees
{
repeated Employee items = 1;
}
Notice that Employee message type defines three fields - employeeID,
firstName, and lastName. Each field has a data type such as int32 or string, and
also a field number. A field number is a numeric value between 1 to 536870911.
Numbers between 19000 and 19999 are reserved and hence can't be used.
The Employees message type is supposed to be a collection of Employee type.
The repeated keyword marks the items field to be a collection of Employee items.
The SelectByID() message type accepts an EmployeeFilter and returns a single
Employee object. The EmployeeFilter contains filtering criteria for an Employee
and looks like this:
message EmployeeFilter
{
int32 employeeID = 1;
}
As you can see, the EmployeeFilter type contains a single field named
employeeID and its data type is int32. The SelectByID() returns a single
Employee matching the specified employeeID value.
The Insert(), Update(), and Delete() methods are similar in that they all
return Empty message. The Insert(), and Update() methods accept an Employee to
be added and Employee to be modified respectively. The Delete() method accepts
an EmployeeFilter containing an EmployeeID of an Employee to be deleted.
This completes the EmployeeCRUD.proto file. This .proto file gets converted
to a C# class upon compilation. I would suggest that you go through the
Prototype Buffer documentation to familiarize the terminology and syntax of the
.proto file.
Now open the appsettings.json file and add the database connection string to
the Northwind database as shown below:
"ConnectionStrings": {
"AppDb": "data source=.;initial catalog=Northwind;
integrated security=true"
}
Then add NuGet package for Microsoft.EntityFrameworkCore.SqlServer and add a
custom DbContext class as shown below:
public class AppDbContext:DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options)
: base(options)
{
}
public DbSet<Employee> Employees { get; set; }
}
The AppDbContext class defines the Employees DbSet. The Employee entity class
used by the AppDbContext is shown below:
public class Employee
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int EmployeeID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
Note that there are now two Employee types - Employee from EmployeeCRUD.proto
file and Employee entity class. Arrange them in meaningful namespaces or give
different names to them if this seems to be confusing to you.
Finally, register the AppDbContext with the DI container This is done in the
ConfigureServices() as shown below:
public void ConfigureServices(IServiceCollection services)
{
services.AddGrpc();
services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(this.config.
GetConnectionString("AppDb")));
}
At this point your project may not compile successfully because you haven't
implemented the service yet. You will do that in the next part of this article.
That's it for now! Keep coding!!
"As you magnetize an iron rod by rubbing it with a magnet again and
again, a flickering mind too becomes one pointed by practicing
meditation again and again."
#AjapaYogaByBipinJoshi