Micro ORMs, alternatives to Entity Framework ? Part 5
Introduction of some Micro ORMs: NPoco
Scenario Used
You can find the scenario used in a last article here.
NPoco’s origin
NPoco is a fork from PetaPoco itself Inspired of Massive.
PetaPoco has been forked a second time: XPoco released in 2017
NPoco
- PetaPoco’s fork
- Same advantages of PetaPoco, with additional features :
- Enriching an existing object
- Supports multiple data sets (like Entity Framework, but more stylish)
- Async queries supported (but not all operations)
- And many others….
- Syntax almost identical to PetaPoco, simpler in most cases
- Simplified relationship management
- No need for mapping attributes like PetaPoco, aliases are better supported
- Testable unitarily
- Less popular than PetaPoco, less active community
Code samples :
Required entities and business objects for our scenario :
public class Orders
{
public Orders() { }
public int Id { get; set; }
public string ProductName { get; set; }
public int? Quantity { get; set; }
public DateTime? Date { get; set; }
}
//Db entity
public class WorkOrder
{
public WorkOrder() { }
public int WorkOrderId { get; set; }
public int ProductID { get; set; }
public int? OrderQty { get; set; }
public int? StockedQty { get; set; }
public int? ScrappedQty { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
public DateTime? DueDate { get; set; }
public int? ScrapReasonID { get; set; }
public DateTime? ModifiedDate { get; set; }
public Product Product { get; set; }
}
//Db entity
public class Product
{
public int ProductID { get; set; }
public string Name { get; set; }
}
Repository sample :
public class NPocoRepository
{
public NPocoRepository()
{ }
public async Task<List> GetOrders()
{
using (var db = new Database("AdventureWorks2014"))
{
var data = await db.QueryAsync(@"SELECT TOP 500 [WorkOrderID] AS Id, P.Name AS ProductName, [OrderQty] AS Quantity, [DueDate] AS Date
FROM [AdventureWorks2014].[Production].[WorkOrder] AS WO
INNER JOIN[Production].[Product] AS P ON P.ProductID = WO.ProductID");
return data.ToList();
// Other syntax
var data2 = await GetWorkOrdersWithProduct(db);
return data2.Select(x => new Orders { Id = x.WorkOrderId, Date = x.DueDate, Quantity = x.OrderQty, ProductName = x.Product.Name }).ToList();
}
}
public void PopulateExistingOrder(Orders order)
{
using (var db = new Database("AdventureWorks2014"))
{
db.FirstOrDefaultInto(order, @"SELECT P.Name AS ProductName, [OrderQty] AS Quantity, [DueDate] AS Date
FROM [AdventureWorks2014].[Production].[WorkOrder] AS WO
INNER JOIN[Production].[Product] AS P ON P.ProductID = WO.ProductID
WHERE WorkOrderID = @0", order.Id);
}
}
public async Task<List> GetWorkOrdersWithProduct()
{
using (var db = new Database("AdventureWorks2014"))
{
return await GetWorkOrdersWithProduct(db);
}
}
private async Task<List> GetWorkOrdersWithProduct(Database db)
{
var data = await db.FetchAsync(@"SELECT TOP 500 WO.*, P.*
FROM [AdventureWorks2014].[Production].[WorkOrder] AS WO
INNER JOIN[Production].[Product] AS P ON P.ProductID = WO.ProductID");
return data.ToList();
}
public Tuple<List,List> GetWorkOrdersAndProducts()
{
using (var db = new Database("AdventureWorks2014"))
{
return db.FetchMultiple<WorkOrder, Product>("SELECT TOP 500 * FROM[AdventureWorks2014].[Production].[WorkOrder];SELECT * FROM [Production].[Product];");
}
}
public async Task Add(WorkOrder workOrder)
{
using (var db = new Database("AdventureWorks2014"))
{
await db.InsertAsync(workOrder);
}
}
public async Task Update(WorkOrder workOrder)
{
using (var db = new Database("AdventureWorks2014"))
{
await db.UpdateAsync(workOrder);
}
}
public async Task Delete(WorkOrder workOrder)
{
using (var db = new Database("AdventureWorks2014"))
{
await db.DeleteAsync(workOrder);
}
}
}
More and more fun ? 😉
