Popularity
3.5
Growing
Activity
9.5
Growing
205
11
27

Description

A hybrid ORM library for .NET.

Package: https://www.nuget.org/packages/RepoDb Documentation: https://repodb.readthedocs.io/en/latest/

Follow @mike_pendon at Twitter.

Programming language: C#
Tags: Repository     ORM     Database     Micro-orm     Dotnet     POCO     Dotnetcore    

RepoDb alternatives and similar packages

Based on the "ORM" category

Do you think we are missing an alternative of RepoDb or a related project?

Add another 'ORM' Package

README

RepoDb

A hybrid ORM library for .NET.

Package: https://www.nuget.org/packages/RepoDb
Documentation: https://repodb.readthedocs.io/en/latest/

Follow @mike_pendon at Twitter.

Highlight

  • RepoDb is the fastest and the most efficient ORM library in .NET as per the result of RawDataAccessBencher. You can see the actual execution result here.
  • RepoDb is covered by thousand of major business related Unit Tests and Integration Tests.

Builds

Project/Solution Results
RepoDb.Core Build status
RepoDb.Core.UnitTest Build status
RepoDb.Core.IntegrationTest Build status
RepoDb.SqLite Build status
RepoDb.SqLite.UnitTest Build status
RepoDb.SqLite.IntegrationTest Build status

High-Level Architecture

Why RepoDb?

Highlights

  • RepoDb is the fastest and the most efficient .NET ORM Library (in set-fetches) as per the result of RawDataAccessBencher.
  • RepoDb is covered by thousand of major business related Unit Tests and Integration Tests.

Why RepoDb

  • It is very fast in CRUD operations.
  • It is very efficient in memory usage.
  • It is highly extensible.
  • It is easy to switch between lightweight and method-based operations.
  • It is simple, fluent and clean.
  • It is easy to write RawSql statements.
  • It is easy to cache the data.
  • It is well covered by Unit/Integration tests.
  • It has Batch operations.
  • It has Bulk-Insert operation.
  • It has massive ORM operations.
  • It has massive reusable extension methods.
  • It has Async operations.
  • It has Enumeration supports.
  • It has Multi-ResultSet query operations.
  • It has Type mapping.
  • It has Query Hints.
  • It has built-in Repositories.
  • It has built-in Resolvers.
  • It has Dynamic Expressions support.
  • It has Linq Expressions support.
  • It has Table-Based call operations.
  • It has an extensible Tracers.
  • It has an extensible DB Helpers.
  • It has an extensible DB Settings.
  • It has an extensible Statement Builders.
  • It has ADO.NET transaction supports.
  • It is always free!

Documentation

Project

Features

  • Asynchronous Operations
  • Batch Operations
  • Bulk Operations
  • Caching
  • Connection Persistency
  • Database Helpers
  • Database Settings
  • Expression Trees
  • Extension Methods
  • Field Mapping
  • Inline Hints
  • Massive Operations (Generics/Explicits/MethodCalls/TableBased)
  • Multi-Resultset Query
  • Query Builder
  • Repositories
  • Resolvers (CLR Types, DB Types)
  • Statement Builder
  • Tracing
  • Transaction
  • Type Mapping

Code Samples

Let us say you have a customer class named Customer that has an equivalent table in the database named [dbo].[Customer].

public class Customer
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public bool IsActive { get; set; }
    public DateTime LastUpdatedUtc { get; set; }
    public DateTime CreatedDateUtc { get; set; }
}

Query

Via PrimaryKey:

using (var connection = new SqlConnection(ConnectionString))
{
    var customer = connection.Query<Customer>(10045);
}

Via Dynamic:

using (var connection = new SqlConnection(ConnectionString))
{
    var customer = connection.Query<Customer>(new { Id = 10045 });
}

Via Expression:

using (var connection = new SqlConnection(ConnectionString))
{
    var customer = connection.Query<Customer>(c => c.Id == 10045);
}

Via Object:

using (var connection = new SqlConnection(ConnectionString))
{
    var customer = connection.Query<Customer>(new QueryField(nameof(Customer.Id), 10045));
}

Query(TableName)

Via PrimaryKey:

using (var connection = new SqlConnection(ConnectionString))
{
    var customer = connection.Query("Customer", 10045);
}

Via Dynamic:

using (var connection = new SqlConnection(ConnectionString))
{
    var customer = connection.Query("Customer", new { Id = 10045 });
}

Via Object:

using (var connection = new SqlConnection(ConnectionString))
{
    var customer = connection.Query("Customer", new QueryField(nameof(Customer.Id), 10045));
}

Via Object (targetting few fields):

using (var connection = new SqlConnection(ConnectionString))
{
    var customer = connection.Query("Customer", new QueryField(nameof(Customer.Id), 10045),
        Field.From("Id", "FirstName", "LastName"));
}

Insert

var customer = new Customer
{
    FirstName = "John",
    LastName = "Doe",
    IsActive = true
};
using (var connection = new SqlConnection(ConnectionString))
{
    var id = connection.Insert<Customer, int>(customer);
}

Insert(TableName)

var customer = new
{
    FirstName = "John",
    LastName = "Doe",
    IsActive = true,
    LastUpdatedUtc = DateTime.Utc,
    CreatedDateUtc = DateTime.Utc
};
using (var connection = new SqlConnection(ConnectionString))
{
    var id = connection.Insert<int>("Customer", customer);
}

Update

Via DataEntity:

using (var connection = new SqlConnection(ConnectionString))
{
    var customer = connection.Query<Customer>(10045);
    customer.FirstName = "John";
    customer.LastUpdatedUtc = DateTime.UtcNow;
    var affectedRows = connection.Update<Customer>(customer);
}

Via PrimaryKey:

using (var connection = new SqlConnection(ConnectionString))
{
    var customer = connection.Query<Customer>(10045);
    customer.FirstName = "John";
    customer.LastUpdatedUtc = DateTime.UtcNow;
    var affectedRows = connection.Update<Customer>(customer, 10045);
}

Via Dynamic:

using (var connection = new SqlConnection(ConnectionString))
{
    var customer = connection.Query<Customer>(10045);
    customer.FirstName = "John";
    customer.LastUpdatedUtc = DateTime.UtcNow;
    var affectedRows = connection.Update<Customer>(customer, new { Id = 10045 });
}

Via Expression:

using (var connection = new SqlConnection(ConnectionString))
{
    var customer = connection.Query<Customer>(10045);
    customer.FirstName = "John";
    customer.LastUpdatedUtc = DateTime.UtcNow;
    var affectedRows = connection.Update<Customer>(customer, e => e.Id == 10045);
}

Via Object:

using (var connection = new SqlConnection(ConnectionString))
{
    var customer = connection.Query<Customer>(10045);
    customer.FirstName = "John";
    customer.LastUpdatedUtc = DateTime.UtcNow;
    var affectedRows = connection.Update<Customer>(customer, new QueryField(nameof(Customer.Id), 10045));
}

Update(TableName)

Via Dynamic Object:

using (var connection = new SqlConnection(ConnectionString))
{
    var customer = new
    {
        Id = 10045,
        FirstName = "John",
        LastUpdatedUtc = DateTime.UtcNow
    };
    var affectedRows = connection.Update("Customer", customer);
}

Via PrimaryKey:

using (var connection = new SqlConnection(ConnectionString))
{
    var customer = new
    {
        FirstName = "John",
        LastUpdatedUtc = DateTime.UtcNow
    };
    var affectedRows = connection.Update("Customer", customer, 10045);
}

Via Dynamic:

using (var connection = new SqlConnection(ConnectionString))
{
    var customer = new
    {
        FirstName = "John",
        LastUpdatedUtc = DateTime.UtcNow
    };
    var affectedRows = connection.Update("Customer", customer, new { Id = 10045 });
}

Via Object:

using (var connection = new SqlConnection(ConnectionString))
{
    var customer = new
    {
        FirstName = "John",
        LastUpdatedUtc = DateTime.UtcNow
    };
    var affectedRows = connection.Update("Customer", customer, new QueryField("Id", 10045));
}

Delete

Via DataEntity:

using (var connection = new SqlConnection(ConnectionString))
{
    var customer = connection.Query<Customer>(10045);
    var deletedCount = connection.Delete<Customer>(customer);
}

Via PrimaryKey:

using (var connection = new SqlConnection(ConnectionString))
{
    var deletedCount = connection.Delete<Customer>(10045);
}

Via Dynamic:

using (var connection = new SqlConnection(ConnectionString))
{
    var deletedCount = connection.Delete<Customer>(new { Id = 10045 });
}

Via Expression:

using (var connection = new SqlConnection(ConnectionString))
{
    var deletedCount = connection.Delete<Customer>(c => c.Id == 10045);
}

Via Object:

using (var connection = new SqlConnection(ConnectionString))
{
    var deletedCount = connection.Delete<Customer>(new QueryField(nameof(Customer.Id), 10045));
}

Delete(TableName)

Via PrimaryKey:

using (var connection = new SqlConnection(ConnectionString))
{
    var deletedCount = connection.Delete("Customer", 10045);
}

Via Dynamic:

using (var connection = new SqlConnection(ConnectionString))
{
    var deletedCount = connection.Delete("Customer", { Id = 10045 });
}

Via Object:

using (var connection = new SqlConnection(ConnectionString))
{
    var deletedCount = connection.Delete("Customer", new QueryField(nameof(Customer.Id), 10045));
}

Merge

var customer = new Customer
{
    FirstName = "John",
    LastName = "Doe",
    IsActive = true,
    LastUpdatedUtc = DateTime.Utc,
    CreatedDateUtc = DateTime.Utc
};
using (var connection = new SqlConnection(ConnectionString))
{
    var qualifiers = new []
    {
        new Field(nameof(Customer.FirstName)),
        new Field(nameof(Customer.LastName)),
    };
    var mergeCount = connection.Merge<Customer>(customer, qualifiers);
}

Merge(TableName)

var customer = new Customer
{
    FirstName = "John",
    LastName = "Doe",
    IsActive = true
};
using (var connection = new SqlConnection(ConnectionString))
{
    var qualifiers = new []
    {
        new Field(nameof(Customer.FirstName)),
        new Field(nameof(Customer.LastName)),
    };
    var mergeCount = connection.Merge("Customer", customer, qualifiers);
}

ExecuteQuery

You can create a class with combined properties of different tables or with stored procedures. It does not need to be 100% identical to the schema, as long the property of the class is part of the result set.

public class ComplexClass
{
    public int CustomerId { get; set; }
    public int OrderId { get; set; }
    public int ProductId { get; set; }
    public string CustomerName { get; set; }
    public string ProductName { get; set; }
    public DateTime ProductDescription { get; set; } // This is not in the CommandText, will be ignored
    public DateTime OrderDate { get; set; }
    public int Quantity { get; set; }
    public double Price { get; set; }
}

Then you can create this command text.

var commandText = @"SELECT C.Id AS CustomerId
    , O.Id AS OrderId
    , P.Id AS ProductId
    , CONCAT(C.FirstName, ' ', C.LastName) AS CustomerName
    , P.Name AS ProductName
    , O.OrderDate
    , O.Quantity
    , P.Price
    , (O.Quatity * P.Price) AS Total /* Note: This is not in the class, but still it is valid */
FROM [dbo].[Customer] C
INNER JOIN [dbo].[Order] O ON O.CustomerId = C.Id
INNER JOIN [dbo].[OrderItem] OI ON OI.OrderId = O.Id
INNER JOIN [dbo].[Product] P ON P.Id = OI.ProductId
WHERE (C.Id = @CustomerId)
    AND (O.OrderDate BETWEEN @OrderDate AND DATEADD(DAY, 1, @OrderDate));";

Via Dynamic:

using (var connection = new SqlConnection(ConnectionString))
{
    var customer = connection.ExecuteQuery<ComplexClass>(commandText, new { CustomerId = 10045, OrderDate = DateTime.UtcNow.Date });
}

Via Object:

using (var connection = new SqlConnection(ConnectionString))
{
    var queryGroup = new QueryGroup(new []
    {
        new QueryField("CustomerId", 10045),
        new QueryField("OrderDate", DateTime.UtcNow.Date)
    });
    var customer = connection.ExecuteQuery<Customer>(commandText, queryGroup);
}

The ExecuteQuery method is purposely not being supported by Expression based query as we are avoiding the user to bind the complex-class to its target query text.

Note: The most optimal when it comes to performance is to used the Object-Based.

StoredProcedure

Using the complex type above. If you have a stored procedure like below.

DROP PROCEDURE IF EXISTS [dbo].[sp_get_customer_orders_by_date];
GO
CREATE PROCEDURE [dbo].[sp_get_customer_orders_by_date]
(
    @CustomerId INT
    , @OrderDate DATETIME2(7)
)
AS
BEGIN
    SELECT C.Id AS CustomerId
        , O.Id AS OrderId
        , P.Id AS ProductId
        , CONCAT(C.FirstName, ' ', C.LastName) AS CustomerName
        , P.Name AS ProductName
        , O.OrderDate
        , O.Quantity
        , P.Price
        , (O.Quatity * P.Price) AS Total /* Note: This is not in the class, but still it is valid */
    FROM [dbo].[Customer] C
    INNER JOIN [dbo].[Order] O ON O.CustomerId = C.Id
    INNER JOIN [dbo].[OrderItem] OI ON OI.OrderId = O.Id
    INNER JOIN [dbo].[Product] P ON P.Id = OI.ProductId
    WHERE (C.Id = @CustomerId)
        AND (O.OrderDate BETWEEN @OrderDate AND DATEADD(DAY, 1, @OrderDate));
END

Then it can be called as below.

Via Dynamic:

using (var connection = new SqlConnection(ConnectionString))
{
    var customer = connection.ExecuteQuery<ComplexClass>("[dbo].[sp_get_customer_orders_by_date]",
        param: new { CustomerId = 10045, OrderDate = DateTime.UtcNow.Date },
        commandType: CommandType.StoredProcedure);
}

Via Object:

using (var connection = new SqlConnection(ConnectionString))
{
    var queryGroup = new QueryGroup(new []
    {
        new QueryField("CustomerId", 10045),
        new QueryField("OrderDate", DateTime.UtcNow.Date)
    });
    var customer = connection.ExecuteQuery<Customer>(commandText, queryGroup,
        commandType: CommandType.StoredProcedure);
}

Please visit our documentation for further details about the codes.