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 ? 😉