Following lab setup, in this post, I will show how to use dotnet core to access Postgres db.
Summary
- Create a dotnet core console project
- use Entity Framework to generate Entity Framework context and entity code
- write code to run a query using Entity Framework
- write code to run a query using ADO.Net/Npgsql
- run a speed test
Create a dotnet project and add Postgres packages
dotnet new console -n CmdlineApp
cd CmdlineApp
dotnet add package Npgsql --version 4.0.5
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL --version 2.2.0
# set up connection string
$cnstr = "Host={0};Database={1};Username={2};Password={3}" -f $env:PGHOST,$env:PGDATABASE,$env:PGUSER,$env:PGPASSWORD
dotnet ef dbcontext scaffold $cnstr Npgsql.EntityFrameworkCore.PostgreSQL
# brunoContext.cs and College.cs generated
Write some code
Source code on my github repo
EF query
int ret = 0;
brunoContext.ConnectionString = ConnectionString;
string sqltext = (!queryByName) ? "select * from yin.college where id = {0}"
:"select * from yin.college where earnings is not null and name ~* {0} order by earnings desc limit 20";
using (var context = new brunoContext())
{
Task<List<College>> task = context.College
.FromSql(sqltext, val)
.ToListAsync();
Console.WriteLine("Waiting for query to finish ...");
var college = await task;
foreach(var item in college){
Console.WriteLine(item.Info);
Log.Information(item.Info);
}
ret = college.Count;
}
return ret;
ADO.Net query: a little bit more work
DBNull value needs to be handled, this can be achieved using the private method:
decimal? ToDecimal(Object v){
return (v is System.DBNull)? null: (decimal?)v;
}
Each column value has to be handled manually:
using(var cn = new NpgsqlConnection(ConnectionString)){
string sqltext = (!queryByName) ? "select * from yin.college where id = @p1"
:"select * from yin.college where earnings is not null and name ~* @p1 order by earnings desc limit 20";
await cn.OpenAsync();
var cmd = new NpgsqlCommand(sqltext, cn);
var p1 = cmd.Parameters.Add("p1", NpgsqlDbType.Varchar, 32);
p1.Value = val;
var r = await cmd.ExecuteReaderAsync();
int total = 0;
while(r.Read()){
Object[] values = new Object[r.FieldCount];
int fieldCount = r.GetValues(values);
College item = new College{
Id = (string)values[0], Name = (string)values[1],City = (string)values[2],State = (string)values[3],
Zip = (string)values[4],Region = (int)values[5],
Latitude = ToDecimal(values[6]), Longitude = ToDecimal(values[7]),
AdmRate = ToDecimal(values[8]), SatAvg = ToDecimal(values[9]), ActAvg=ToDecimal(values[10]),
Earnings=ToDecimal(values[11]), Cost=ToDecimal(values[12]),Enrollments=ToDecimal(values[13])
};
Log.Information(item.Info);
Console.WriteLine(item.Info);
total ++;
}
ret = total;
run a speed test
Use a Powershell script
$testEF = {
dotnet run -n cali -qt ef
}
$testSimple = {
dotnet run -n cali
}
Function runTest{
Param(
[scriptblock]$Script
)
$w = New-Object System.Diagnostics.Stopwatch
$w.Start()
& $Script | Out-Null
$w.Stop()
# "`n{0:#,###.#0} milli seconds used`n" -f $w.Elapsed.TotalMilliseconds
$w.Elapsed.TotalMilliseconds
}
$results = @()
1 .. 25 | % {
$a = runTest -Script $testEF
$b = runTest -Script $testSimple
$results += New-Object -TypeName psobject -Property @{EF=$a; Simple=$b; Difference=$b-$a }
}
$results
Test results
EF runs on top of Npgsql, it’s easy to predict that ADO/Npgsql runs faster than EF:
> Difference Simple EF
> ---------- ------ --
> -890.4726 2003.5534 2894.026
> -790.5495 2026.9623 2817.5118
> -803.0365 2023.1614 2826.1979
> -683.2189 2137.6329 2820.8518
> -787.4604 2067.4506 2854.911
> -873.2238 2066.3301 2939.5539
> -828.5192 2011.5325 2840.0517
> -788.0466 2070.0426 2858.0892
> -757.0905 2055.0067 2812.0972
> -745.6193 2085.95 2831.5693
> -812.5492 2031.2828 2843.832
> -778.6706 2036.892 2815.5626
> -779.2398 2032.2943 2811.5341
> -763.1625 2045.6339 2808.7964
> -911.0323 2029.7009 2940.7332
> -821.3651 1992.6945 2814.0596
> -802.1631 2011.2111 2813.3742
> -781.8481 2038.95 2820.7981
> -787.0569 2059.4261 2846.483
> -773.6388 2036.2037 2809.8425
> -794.3785 2027.4133 2821.7918
> -811.3318 2031.5567 2842.8885
> -811.1682 2000.7685 2811.9367
> -809.3262 2014.9895 2824.3157
> -763.4612 2029.836 2793.2972
>