Introduction

After asking on /r/csharp, the general opinion was: "Use Dapper, but keep Entity Framework for the generation of the schema and identity authentication."

This is the comment from another user:

There's no reason you can't use both. Use EF and all the built in EF stuff for identity so you're not reinventing the wheel. And then use dapper for all of your app stuff.
I recently did this and it turned out just fine. I even extended the base EF models to give the user a few extra properties without issue."

And a different user added some links:

I haven't played a lot with the updated Identity framework (3.0) for EF7 and .NET Core, so I'm not sure how much it has changed. For Identity 2.0, the links below will give you most of what you need to get this set up:
[1] https://www.asp.net/identity/overview/extensibility/overview-of-custom-storage-providers-for-aspnet-identity
[2] https://www.captechconsulting.com/blogs/Customizing-the-ASPNET-Identity-Data-Model-with-the-Entity-Framework-Fluent-API--Part-1
[3] https://www.asp.net/identity/overview/extensibility/change-primary-key-for-users-in-aspnet-identity

Startegy

I'll mimic the strategy from this github project (thanks to drbergeron for that):

  1. Create a web application with Entity Framework
  2. Create an API with Dapper

The web app will manage the authentication, and will then call the API for all other interactions with the database.

Creating the web application

Create a AspNet Core Web application with Visual Studio. Select "authentication" -> "individual accounts".

// TODO: connect to postgresql

Click "register" and create a new account. This will let Entity Framework create the authentication tables.

Example of a Controller

[Authorize]
public class GameController : Controller
{
    // GET: Game
    private IOptions<ConnectionStrings> _conn;
    // Stores UserManager
    private readonly UserManager<ApplicationUser> _manager;
 
    public GameController(IOptions<ConnectionStrings> optIn, UserManager<ApplicationUser> manager)
    {
        _conn = optIn;
        _manager = manager;
    }
 
    public IActionResult Index()
    {
        // Manage the user with Entity Framework
        // (ApplicationUser is an extension of IdentityUser)
        var user = _manager.GetUserAsync(HttpContext.User).Result;
        var friendlyID = user?.FriendlyUserId ?? -1;
 
        // Call the API:
        var con = new API.Controllers.GameController(_conn);
        var resp = con.GetDefaultGames(friendlyID);
 
        return View(resp.Value);
    }
}
 
// \Models\ApplicationUser.cs:
// (Add profile data for application users by adding properties to the IdentityUser class)
public class ApplicationUser : IdentityUser
{
    public long? FriendlyUserId { get; set; }
}
 
// \Data\ApplicationDbContext.cs:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }
 
    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);
        builder.Entity(typeof(ApplicationUser)).Property<long?>("FriendlyUserId").UseSqlServerIdentityColumn();
    }
}

Creating the API

Example of a Controller

[Route("api/[controller]")]
public class GameController : Controller
{
    private GameRepository _gameRepo;
 
    public GameController(IOptions<ConnectionStrings> connIn)
    {
        _gameRepo = new GameRepository(connIn.Value.DefaultConnection);
    }
 
    // GET: api/values
    [HttpGet("default/{id}")]
    public IActionResult GetDefaultGames(long id)
    {
        var getGamesTask = _gameRepo.GetManyGames(id);
        var Games = getGamesTask.Result;
        if (Games.Count() == 0)
            return NoContent();
        else
            return Ok(Games);
    }
}

Example of Dapper model-repository

// Model:
public class Game
{
    public long Id { get; set; }
    public GameTypeEnum TypeId { get; set; }
    public long UserId { get; set; }
    public int Year { get; set; }
    public int Day { get; set; }
    public int RollsTaken { get; set; }
    public bool isClosed { get; set; }
    public GameWinType isWinningGame { get; set; }
    public int winAmount { get; set; }
    public int AppliedToAccount { get; set; }
}
 
// Repository:
public class GameRepository
{
    private SqlConnection _conn;
 
    public GameRepository(string connStr)
    {
        _conn = new SqlConnection(connStr);
    }
 
    public async Task<Game> GetGameById(long Id)
    {
        var sql = $@"Select Id, TypeId, UserId, Year, Day, RollsTaken, isClosed, isWinningGame, winAmount, AppliedToAccount
                    From Games
                    where Id = @id";
 
        return await _conn.QueryFirstOrDefaultAsync<Game>(sql, new { id = Id });
    }
}

Comments

Becoming a Wikidot member is free and easy: create an account.

You have to be a Wikidot member to add comments to a Wikidot blog.

Add a New Comment