adamfoneil / Dapper.CX

A Crud library based on Dapper
MIT License
8 stars 1 forks source link
crud-generator crud-operation crud-operations dapper dapper-extensions

Build status Nuget Nuget

Note: I'm no longer updating this. Please see Dapper.Repository.

Dapper.CX is a CRUD library for SQL Server made with Dapper. It works with POCO classes, where the only model class requirement is that they have a property called Id or an Identity attribute on the class that indicates what its identity property is. int and long identity types are supported. You can use Dapper.CX in two ways:

Wiki links: Why Dapper.CX?, Reference. Note that Dapper.CX doesn't create tables. Please see my ModelSync project for info on that.

Please see my BlazorAO project to see Dapper.CX in action. If you're not familiar with Dapper, I have a PowerPoint Why I Use Dapper for .NET Data Access that's an intro and also shows where Dapper.CX builds upon it.

In a Nutshell

When using the injected service, you'd write CRUD code that looks like this. This example assumes a fictional Employee model class. There are several advantages of using the injected service. One, it integrates nicely with the authenticated user to check permissions or perform audit and change tracking. Two, you can omit the using block that you otherwise need when interacting with a connection. Three, there are some handy overloads that bundle exception handling and more. Here's how to implement the injected service along with a CRUD method reference.

public EmployeesModel(DapperCX<int> data)
{
    Data = data;
}

public DapperCX<int> Data { get; }

public Employee ViewRecord { get; set; }

public async Task OnGetAsync(int id)
{
    ViewRecord = await Data.GetAsync<Employee>(id);
}

public async Task<IActionResult> OnPostSaveAsync(Employee employee)
{
    await Data.SaveAsync(employee);
    return Redirect("/Employees");
}

public async Task<IActionResult> OnPostDeleteAsync(int id)
{
    await Data.DeleteAsync<Employee>(id);
    return Redirect("/Employees");
}

When using the extension methods, it's almost the same thing, but you must open a database connection first. This example assumes a fictional GetConnection method that opens a SQL Server connection.

public Employee ViewRecord { get; set; }

public async Task OnGetAsync(int id)
{
    using (var cn = GetConnection())
    {
        ViewRecord = await cn.GetAsync<Employee>(id);
    }    
}

public async Task<IActionResult> OnPostSaveAsync(Employee employee)
{
    using (var cn = GetConnection())
    {
        await cn.SaveAsync(employee);
        return Redirect("/Employees");
    }
}

public async Task<IActionResult> OnPostDeleteAsync(int id)
{
    using (var cn = GetConnection())
    {
        await cn.DeleteAsync<Employee>(id);
        return Redirect("/Employees");
    }
}

Customizing behaviors with interfaces

There's a lot of functionality you can opt into by implementing interfaces on your model classes from the AO.Models project. See Extending Dapper.CX with Interfaces. Available interfaces are here.

And one other thing...

In addition to the more common strong-typed CRUD operations, Dapper.CX also offers a SqlCmdDictionary feature that gives you a clean way to build INSERT and UPDATE statements dynamically.

One other thing...

If you need a Dictionary-like object to persist in a database, you can implement the abstract class DbDictionary. Use this to store any object with a key, using these supported key types. This can save you the effort of adding a single-use dedicated model class for a more generic storage need. Note that, unlike a Dictinoary<TKey, TValue>, you can use different TValues with different keys, so this is very flexible and still type-safe. The abstract methods Serialize and Deserialize let you provide your Json serialization. See the integration test to see in action, along with the sample implementation.


Please see also Dapper.QX, Dapper.CX's companion library.