Micro ORMs, alternatives to Entity Framework ? Part 9

 

<< Previous article (Part 8)

What conclusion(s) can we make ?

Let’s summarize first principals features we described for each Micro ORM before in a user friendly table here:

Legends :

 Disappointing

 Good

 Excellent

 Yes

 No

 Yes, but not verified

Note that they :

  • All support the execution of stored procedures, views, functions
  • Are all protected from SQL injection (queries parameterization)

What we liked ?

  • NPoco for simplicity of its syntax and performance
  • Dapper for its outstanding performance and its amazing community
  • OrmLite for its double LINQ-like and SQL syntax, and for its rich functionalities and performance

Finally….

Even if we love some Micro ORMs and they are more performant than Entity Framework, they don’t provide all Entity Framework’s functionalities, and they don’t support unit tests as Entity Framework does (by mocking its DbContext).

In fact it depends on what you are looking for 🙂

I hope this suite of articles helped you to make a choice 😉

If you need to check the source code, you can find it here : https://github.com/AnthonyGiretti/MicroOrmDemo.net

Micro ORMs, alternatives to Entity Framework ? Part 8

 

<< Previous article (Part 7)

Performance comparisons

I did some benchmarks, only with Select query.

First benchmark scenario

I used single query that bring back from database 500 rows, here the query:

 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

Second benchmark scenario

I used a serie of 500 queries that returns 1 row:

SELECT [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
WHERE WorkOrderID = @Id

Let’s see what happened….

 

Most of time Micro Orms are faster than Entity Framework, but less than ADO.NET

 

What conclusions can we make ?

Micro ORMs, alternatives to Entity Framework ? Part 5

 

<< Previous article (Part 4)

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 :
  1.  Enriching an existing object
  2.  Supports multiple data sets (like Entity Framework, but more stylish)
  3.  Async queries supported (but not all operations)
  4.  And many others….
  • Syntax almost identical to PetaPoco, simpler in most cases
  1.  Simplified relationship management
  2.  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 ? 😉

 

The next is OrmLite !