It depends, lets look at three approaches.
Dapper
public static async Task<IEnumerable<Categories>> GetCategories()
{
await using SqlConnection cn = new(ConnectionString());
return await cn.QueryAsync<Categories>(SqlStatements.GetCategories);
}
EF Core
List<Categories> categories = await _context.Categories.ToListAsync();
ADO
var list = new List<Category>();
using var cn = new SqlConnection() { ConnectionString = ConnectionString };
var selectStatement = "SELECT CategoryID, CategoryName FROM dbo.Categories;";
using var cmd = new SqlCommand() { Connection = cn, CommandText = selectStatement };
cn.Open();
var reader = cmd.ExecuteReader();
while (reader.Read())
{
list.Add(new Category() { Id = reader.GetInt32(0), Name = reader.GetString(1) });
}
return list;
For a novice I would recommend EF Core first, ADO second, Dapper third.
For a seasoned developer EF Core first, Dapper second, ADO third.
Why the difference in skill level? For the novice it may appear easy at first but once into joins it can be difficult but not so for the seasoned developer but could also be difficult for a intermediate developer depending on how well one learns.
Joins are done very differently with Dapper e.g. using splitOn.
public static async Task<List<Customers>> CustomersWithContacts1()
{
await using SqlConnection cn = new(ConnectionString());
var list = cn.Query<Customers, Contacts, Countries, Customers>(
SQL.CustomerWithContacts1(), (customers,contacts, country) =>
{
customers.Contact = contacts;
customers.ContactId = contacts.ContactId;
customers.CountryIdentifier = country.CountryIdentifier;
customers.CountryIdentifierNavigation = country;
return customers;
}, splitOn: "ContactId,CountryIdentifier");
return list.ToList();
}
With EF Core joins are both with .Include, no mess, no fuss.
public async Task<List<Customers>> OrderByOnNavigation(string ordering)
{
return await _context.Customers
.Include(c => c.CountryIdentifierNavigation)
.Include(c => c.Contact)
.Include(c => c.ContactTypeIdentifierNavigation)
.OrderByColumn(ordering)
.ToListAsync();
}