Dapper DateOnly/TimeOnly

Karen Payne - Jan 15 - - Dev Community

Dapper is a great addition to working with databases when working with a Microsoft data provider that requires a connection and command object and when required command parameters. Dapper at this point in time does not handle DateOnly and TimeOnly Struct.

To handle DateOnly and TimeOnly, the following handler/mappers will provide methods to work with DateOnly and TimeOnly.

public class SqlDateOnlyTypeHandler : SqlMapper.TypeHandler<DateOnly>
{
    public override void SetValue(IDbDataParameter parameter, DateOnly date) 
        => parameter.Value = date.ToDateTime(new TimeOnly(0, 0));
    public override DateOnly Parse(object value) => DateOnly.FromDateTime((DateTime)value);
}

public class SqlTimeOnlyTypeHandler : SqlMapper.TypeHandler<TimeOnly>
{
    public override void SetValue(IDbDataParameter parameter, TimeOnly time)
    {
        parameter.Value = time.ToString();
    }

    public override TimeOnly Parse(object value) => TimeOnly.FromTimeSpan((TimeSpan)value);
}
Enter fullscreen mode Exit fullscreen mode

Usage

Add both or one of the class to a project then in the constructor of the class used to work data with Dapper.

using Dapper;
using Microsoft.Data.SqlClient;
using System.Data;
using kp.Dapper.Handlers;
using sqlserverApp.Models;
using static System.DateTime;

namespace sqlserverApp.Classes;
internal class Operations
{
    private IDbConnection _cn;
    public Operations()
    {
        _cn = new SqlConnection("Your connection string");
        SqlMapper.AddTypeHandler(new SqlDateOnlyTypeHandler());
        SqlMapper.AddTypeHandler(new SqlTimeOnlyTypeHandler());
    }
}
Enter fullscreen mode Exit fullscreen mode

Now when needed to work with DateOnly and/or TimeOnly.

internal class Operations
{
    private IDbConnection _cn;
    /// <summary>
    /// Setup connection and DateOnly and TimeOnly handlers from Dapper.Handlers class project or NuGet package
    /// </summary>
    public Operations()
    {
        _cn = new SqlConnection(ConnectionString());
        SqlMapper.AddTypeHandler(new SqlDateOnlyTypeHandler());
        SqlMapper.AddTypeHandler(new SqlTimeOnlyTypeHandler());
    }

    public List<Test1> GetAll()
        => _cn.Query<Test1>("SELECT Id, DateOnly, TimeOnly FROM dbo.Test1;").ToList();

    public async Task<List<Test1>> GetAllAsync()
        => (await _cn.QueryAsync<Test1>("SELECT id, GenderType FROM Genders")).AsList();

    public bool Update()
    {
        var statement = "UPDATE dbo.Test1 SET DateOnly = @dataonly,TimeOnly = @timeonly  WHERE Id = @id";
        var affected = _cn.Execute(statement, new
        {
            dataonly = DateOnly.FromDateTime(Now),
            timeonly = TimeOnly.FromDateTime(Now),
            id = 10
        });

        return affected == 1;
    }
}
Enter fullscreen mode Exit fullscreen mode

Package the code

When there are many projects that require handlers to work with DateOnly and TimeOnly the smart path is to create a class project with the handlers, compile and pack as an NuGet package so that when needed simply add the package to a project dependencies.

Actually there is no need to package the code as it has already been done.

NuGet page for DateOnly and TimeOnly for Dapper

Download page

If a developer wants to personalize the code, download the source code, modify and pack to a local NuGet package.

To create a local NuGet package source, create a folder, point to the folder as shown below. Once this is done adding the package is done through NuGet package manager.

NuGet package manager in Microsoft Visual Studio 2022

Summary

By placing the code to handle DateOnly and TimeOnly into a class project or a NuGet package allows easy and consistent access to the handler code without the need to locate the code or copy and paste into a project each time either both or one handler is needed.

Resources

Unsure if Dapper is right for you?

Check out this class which was replace with this class which cut the code in half.

License

No credits are required using a modified version of this code.

Source code

Clone this GitHub repository for use without using the NuGet package or placing the package in a local NuGet folder.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .