Entity Framework Core and DevExpress XPO: Two ORM Solutions

Now that DevExpress is defaulting EF Core in the XAF wizard a lot of our students ask what should they use or why EF Core is the default ORM now?

Update 5/3/2023 : Here is the official DevExpress documentation explaining the reasoning behind their decision : Why We Recommend EF Core over XPO for New Development.

Ok, let’s continue and see the whole picture. What is an ORM?

Object-Relational Mapping (ORM) is a popular technique used in software development to bridge the gap between object-oriented programming and relational databases. It simplifies database operations by mapping objects in the code to database tables, allowing developers to work with databases using familiar object-oriented concepts.

If you read the paragraph above it seems like a straight forward concept. Well, the ORM world has had so much love and hate that it seems that everyone has a different stance about them. If you want to go deep take a look at this two articles:

https://blog.codinghorror.com/object-relational-mapping-is-the-vietnam-of-computer-science/

https://martinfowler.com/bliki/OrmHate.html

In this post we will keep it simple. Let’s talk about the more debated pros and cons of using and ORM:

Pros:

  1. Improved productivity: ORM tools automate repetitive tasks, such as creating and managing database connections, resulting in faster development.
  2. Abstraction: ORMs provide an abstraction layer, allowing developers to focus on business logic instead of low-level database operations.
  3. Maintainability: Using an ORM simplifies code maintenance by enforcing a consistent structure and reducing the amount of raw SQL.

Cons:

  1. Performance overhead: ORM tools may introduce performance overhead, especially when handling large data sets or complex queries.
  2. Limited control: ORMs often prioritize simplicity over control, which may lead to issues when developers need to fine-tune database interactions.

Now to our daily bread and butter with XAF:

Two widely-used ORM solutions are Entity Framework Core (EF Core) and DevExpress eXpress Persistent Objects (XPO).

Entity Framework Core (EF Core)

EF Core is an open-source, lightweight, and extensible ORM developed by Microsoft. It is a significant rewrite of the original Entity Framework, designed to support multiple platforms, including .NET Core and .NET Framework.

Advantages:

  1. Cross-platform: EF Core works seamlessly across different platforms, such as Windows, macOS, and Linux.
  2. LINQ support: EF Core allows developers to query data using Language Integrated Query (LINQ), which enhances code readability and maintainability.
  3. Code-First approach: EF Core supports a code-first approach, enabling developers to generate database tables and relationships based on their code.

Disadvantages:

  1. Limited support for complex queries: EF Core may struggle with complex queries, resulting in suboptimal SQL generation.
  2. Slower performance: EF Core may have performance issues compared to other ORM solutions, especially when handling a large number of entities.

DevExpress XPO (eXpress Persistent Objects)

DevExpress XPO is a mature and feature-rich ORM tool developed by DevExpress. It supports various platforms, such as .NET Core, .NET Framework, and Xamarin.

Advantages:

  1. Flexible data model: XPO offers a robust and flexible data model that can easily map complex object hierarchies and relationships.
  2. Customizable: XPO provides a high level of customization, allowing developers to fine-tune performance and data access.
  3. Support for multiple databases: XPO supports a wide range of database systems, including SQL Server, MySQL, Oracle, and PostgreSQL.

Disadvantages:

  1. Unlike EF Core, XPO is not open-source, which may deter some developers from using it.
  2. Smaller Community

Let’s see some code:

EF Core

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore;

namespace EfCoreConsoleApp
{
    public class BlogContext : DbContext
    {
        public DbSet<Blog> Blogs { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer(@"Server=localhost;Database=BlogDb;Trusted_Connection=True;");
        }
    }

    public class Blog
    {
        public int BlogId { get; set; }
        public string Name { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            using (var context = new BlogContext())
            {
                context.Database.EnsureCreated();

                Console.WriteLine("Enter a new blog name:");
                var blogName = Console.ReadLine();

                var blog = new Blog { Name = blogName };
                context.Blogs.Add(blog);
                context.SaveChanges();

                Console.WriteLine("All Blogs:");
                foreach (var b in context.Blogs)
                {
                    Console.WriteLine($"{b.BlogId}: {b.Name}");
                }
            }
        }
    }
}

XPO

using System;
using DevExpress.Xpo;
using DevExpress.Xpo.DB;

namespace XpoConsoleApp
{
    public class Blog : XPObject
    {
        public Blog(Session session) : base(session) { }

        private string _Name;
        public string Name
        {
            get { return _Name; }
            set { SetPropertyValue(nameof(Name), ref _Name, value); }
        }
    }

    public class XpoUnitOfWork : UnitOfWork
    {
        public XpoUnitOfWork() : base(DataLayer)
        {
        }

        private static IDataLayer DataLayer
        {
            get
            {
                var connStr = @"XpoProvider=SqlServer;Server=localhost;Database=BlogDb;Trusted_Connection=True;";
                return XpoDefault.GetDataLayer(connStr, AutoCreateOption.DatabaseAndSchema);
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            using (var unitOfWork = new XpoUnitOfWork())
            {
                Console.WriteLine("Enter a new blog name:");
                var blogName = Console.ReadLine();

                var blog = new Blog(unitOfWork) { Name = blogName };
                unitOfWork.CommitChanges();

                Console.WriteLine("All Blogs:");
                foreach (var b in unitOfWork.Query<Blog>())
                {
                    Console.WriteLine($"{b.Oid}: {b.Name}");
                }
            }
        }
    }
}

In both case we see a simple console application that uses EF Core and DevExpress XPO to add a new blog entry and display all the existing blog entries in the database.

We can also note that the DBContext (EF) and UnitOfWork (XPO) are the bridge between our application and the database.

For XAF:

XPO is still my preferred choice and even if the amount of samples, documentation, etc. is improving for EF Core, XPO has been XAF brother since the beginning and that bonds does not break easily.

Review this two links: (I will wait)

https://docs.devexpress.com/eXpressAppFramework/402972/business-model-design-orm/business-model-design-with-entity-framework-core/use-the-entity-framework-core-data-model

https://docs.devexpress.com/eXpressAppFramework/112600/business-model-design-orm/business-model-design-with-xpo

I know most of this is done already for us on the wizard, but it feels definitely more cumbersome with EF Core and who likes migrations (not me) 😒

Now I am not against the progress and I know the future is EF Core but let me grieve, and got trough the stages and when I get to acceptance…

Then we will do great apps with both ORMs.

XAF out!

PS. Regarding the use of an ORM the answer is you need to know how it works under the hood to help it generate more performant queries and avoid extra loading of data you don’t need. And… knowledge of the database engine used as a properly maintained database makes a huge difference. 😎

I definitely, 9 out of 10 would use an ORM.

#When you get the same questions 3 times you should write an article #NotesToSelf

One thought on “Entity Framework Core and DevExpress XPO: Two ORM Solutions

  1. I have come to love XPO for its simplicity, robustness and overall ease of use.
    I can model an entire database using entirely visual tools. I will definitely continue to use XPO for new projects as long as it is available and does the job.

Leave a Reply

Your email address will not be published.