ASP.NET Core with MySQL and Entity Framework Core

This article shows how to use MySQL with ASP.NET Core 3.1 using Entity Framework Core.

Code: https://github.com/damienbod/AspNetCoreMultipleProject

Posts in this series:

2020-01-10: Updated to ASP.NET Core 3.1
2018-12-05: Updated to ASP.NET Core 2.2 and EF Core 2.2
2017-06-16: Updated to ASP.NET Core 2.1
2017-08-17: Updated to ASP.NET Core 2.0 and Pomelo.EntityFrameworkCore.MySql
2017-02-10: Updated to VS2017 and msbuild
2016-12-01: Updated to ASP.NET Core 1.1

The Entity Framework MySQL package can be downloaded using the NuGet package Pomelo.EntityFrameworkCore.MySql. At present no official provider from MySQL exists for Entity Framework Core which can be used in an ASP.NET Core application.

The Pomelo.EntityFrameworkCore.MySql package can be added to the csproj file.

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <AssemblyName>DataAccessMySqlProvider</AssemblyName>
    <PackageId>DataAccessMySqlProvider</PackageId>
  </PropertyGroup>

  <ItemGroup>
    <ProjectReference Include="..\DomainModel\DomainModel.csproj" />
  </ItemGroup>

  <ItemGroup>
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.0" PrivateAssets="All" />
    <PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="3.1.0" />
  </ItemGroup>

</Project>

The web project which loads the project with EF Core needs to support migrations if you wish to create a database this way.

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <AssemblyName>AspNetCoreMultipleProject</AssemblyName>
    <PackageId>AspNet5MultipleProject</PackageId>
    <StartupObject>AspNetCoreMultipleProject.Program</StartupObject>
  </PropertyGroup>

  <ItemGroup>
    <ProjectReference Include="..\DataAccessMsSqlServerProvider\DataAccessMsSqlServerProvider.csproj" />
    <ProjectReference Include="..\DataAccessMySqlProvider\DataAccessMySqlProvider.csproj" />
    <ProjectReference Include="..\DataAccessPostgreSqlProvider\DataAccessPostgreSqlProvider.csproj" />
    <ProjectReference Include="..\DataAccessSqliteProvider\DataAccessSqliteProvider.csproj" />
    <ProjectReference Include="..\DomainModel\DomainModel.csproj" />
  </ItemGroup>
  
  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.App" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.0" PrivateAssets="All" />
    <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
    <PackageReference Include="Swashbuckle.AspNetCore" Version="5.0.0-rc5" />
  </ItemGroup>
  <ItemGroup>
    <DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0" />
  </ItemGroup>
</Project>

An EfCore DbContext can be added like any other context supported by Entity Framework Core.

using System;
using System.Linq;
using DomainModel.Model;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;

namespace DataAccessMySqlProvider
{ 
    // >dotnet ef migration add testMigration
    public class DomainModelMySqlContext : DbContext
    {
        public DomainModelMySqlContext(DbContextOptions<DomainModelMySqlContext> options) :base(options)
        { }
        
        public DbSet<DataEventRecord> DataEventRecords { get; set; }

        public DbSet<SourceInfo> SourceInfos { get; set; }

        protected override void OnModelCreating(ModelBuilder builder)
        {
            builder.Entity<DataEventRecord>().HasKey(m => m.DataEventRecordId);
            builder.Entity<SourceInfo>().HasKey(m => m.SourceInfoId);

            // shadow properties
            builder.Entity<DataEventRecord>().Property<DateTime>("UpdatedTimestamp");
            builder.Entity<SourceInfo>().Property<DateTime>("UpdatedTimestamp");

            base.OnModelCreating(builder);
        }

        public override int SaveChanges()
        {
            ChangeTracker.DetectChanges();

            updateUpdatedProperty<SourceInfo>();
            updateUpdatedProperty<DataEventRecord>();

            return base.SaveChanges();
        }

        private void updateUpdatedProperty<T>() where T : class
        {
            var modifiedSourceInfo =
                ChangeTracker.Entries<T>()
                    .Where(e => e.State == EntityState.Added || e.State == EntityState.Modified);

            foreach (var entry in modifiedSourceInfo)
            {
                entry.Property("UpdatedTimestamp").CurrentValue = DateTime.UtcNow;
            }
        }
    }
}

In an ASP.NET Core web application, the DbContext is added to the application in the startup class. In this example, the DbContext is defined in a different class library. The MigrationsAssembly needs to be defined, so that the migrations will work. If the context and the migrations are defined in the same assembly, this is not required.

public Startup(IHostingEnvironment env)
{
	var builder = new ConfigurationBuilder()
		.SetBasePath(env.ContentRootPath)
		.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
		.AddJsonFile("config.json", optional: true, reloadOnChange: true);

	Configuration = builder.Build();
}
		
public void ConfigureServices(IServiceCollection services)
{	
	var sqlConnectionString = Configuration.GetConnectionString("DataAccessMySqlProvider");

	services.AddDbContext<DomainModelMySqlContext>(options =>
		options.UseMySQL(
			sqlConnectionString,
			b => b.MigrationsAssembly("AspNetCoreMultipleProject")
		)
	);
}

The application uses the configuration from the config.json. This file is used to get the MySQL connection string, which is used in the Startup class.

{
    "ConnectionStrings": {  
        "DataAccessMySqlProvider": "server=localhost;userid=damienbod;password=1234;database=damienbod;"
        }
    }
}

MySQL workbench can be used to add the schema ‘damienbod’ to the MySQL database. The user ‘damienbod’ is also required, which must match the defined user in the connection string. If you configure the MySQL database differently, then you need to change the connection string in the config.json file.

mySql_ercore_aspnetcore_01

Now the database migrations can be created and the database can be updated.

>
> dotnet ef migrations add mySqlMigration --context DomainModelMySqlContext
>
> dotnet ef database update --context DomainModelMySqlContext
>

If successful, the tables are created.

mySql_ercore_aspnetcore_02

The MySQL provider can be used in a MVC controller using construction injection.

using System.Collections.Generic;
using DomainModel;
using DomainModel.Model;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;

namespace AspNet5MultipleProject.Controllers
{
    [Route("api/[controller]")]
    public class DataEventRecordsController : Controller
    {
        private readonly IDataAccessProvider _dataAccessProvider;

        public DataEventRecordsController(IDataAccessProvider dataAccessProvider)
        {
            _dataAccessProvider = dataAccessProvider;
        }

        [HttpGet]
        public IEnumerable<DataEventRecord> Get()
        {
            return _dataAccessProvider.GetDataEventRecords();
        }

        [HttpGet]
        [Route("SourceInfos")]
        public IEnumerable<SourceInfo> GetSourceInfos(bool withChildren)
        {
            return _dataAccessProvider.GetSourceInfos(withChildren);
        }

        [HttpGet("{id}")]
        public DataEventRecord Get(long id)
        {
            return _dataAccessProvider.GetDataEventRecord(id);
        }

        [HttpPost]
        public void Post([FromBody]DataEventRecord value)
        {
            _dataAccessProvider.AddDataEventRecord(value);
        }

        [HttpPut("{id}")]
        public void Put(long id, [FromBody]DataEventRecord value)
        {
            _dataAccessProvider.UpdateDataEventRecord(id, value);
        }

        [HttpDelete("{id}")]
        public void Delete(long id)
        {
            _dataAccessProvider.DeleteDataEventRecord(id);
        }
    }
}

The controller api can be called using Fiddler:

POST http://localhost:5000/api/dataeventrecords HTTP/1.1
User-Agent: Fiddler
Host: localhost:5000
Content-Length: 135
Content-Type: application/json;
 
{
  "DataEventRecordId":3,
  "Name":"Funny data",
  "Description":"yes",
  "Timestamp":"2015-12-27T08:31:35Z",
   "SourceInfo":
  { 
    "SourceInfoId":0,
    "Name":"Beauty",
    "Description":"second Source",
    "Timestamp":"2015-12-23T08:31:35+01:00",
    "DataEventRecords":[]
  },
 "SourceInfoId":0 
}

The data is added to the database as required.

mySql_ercore_aspnetcore_03

Links:

https://docs.microsoft.com/en-us/ef/core/

https://github.com/SapientGuardian/SapientGuardian.EntityFrameworkCore.MySql

http://dev.mysql.com/downloads/mysql/

Experiments with Entity Framework Core and an ASP.NET Core API

https://docs.efproject.net/en/latest/miscellaneous/connection-strings.html

http://insidemysql.com/howto-starting-with-mysql-ef-core-provider-and-connectornet-7-0-4/

35 comments

  1. Ah u r using webapi in this example

  2. […] ASP.NET Core 1.0 with MySQL and Entity Framework Core […]

  3. […] via ASP.NET Core 1.0 with MySQL and Entity Framework Core — Software Engineering […]

  4. This is cool, but how do I do a DB First with MySQL? Or is that not so simple?

    1. Hi neokushan

      Should work, but I haven’t tried it.

      https://docs.efproject.net/en/latest/platforms/aspnetcore/existing-db.html

      I will give a go myself, thanks for the question

      Greetings Damien

      1. witoong623 · ·

        I already tried it, it doesn’t work because no DesignTimeProviderServicesAttribute in MySql.Data.EntityFrameworkCore package, in case of SQL server, it is in Microsoft.EntityFrameworkCore.SqlServer.Design package.

      2. witoong623 · ·

        I already tried it, it doesn’t work because it require DesignTimeProviderServicesAttribute to be in package.

    1. Cheers thanks for the links, tried this already, but the migrations didn’t work and the extension methods for ASP.NET Core didn’t work for me.

      Greetings Damien

  5. ‘dotnet ef migrations add testMySql’ works fine and it creates a new database in mysql… but
    after ‘dotnet ef database update’ I receive the next message:

    System.NotImplementedException: The method or operation is not implemented.
    at MySQL.Data.EntityFrameworkCore.Migrations.Internal.MySQLHistoryRepository.get_ExistsSql()
    at Microsoft.EntityFrameworkCore.Migrations.HistoryRepository.Exists()
    at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.Migrate(String targetMigration)
    at Microsoft.EntityFrameworkCore.Design.MigrationsOperations.UpdateDatabase(String targetMigration, String contextType)
    at Microsoft.EntityFrameworkCore.Tools.Cli.DatabaseUpdateCommand.c__DisplayClass0_0.b__0()
    at Microsoft.Extensions.CommandLineUtils.CommandLineApplication.Execute(String[] args)
    at Microsoft.EntityFrameworkCore.Tools.Cli.Program.Main(String[] args)

    any suggestion?

    thank you

    1. Hi Carlos
      Which provider are you using, or are you testing with this src code? You also need to create an empty schemaand user first
      Greetings Damien

      1. thank you for your response

        I’ve tried follow your guide but using the official mysql connector. And now I created a new project based in a previous example but I get the same issue.

        my code is here https://github.com/careuno/newtestEfcoreMysql

        thank you damienbod for your attention.

      2. The migrations do not work for the official provider. Use either of the other 2 and it should work. I use SapientGuardian.EntityFrameworkCore.MySql and this works perfect.

        Greetings Damien

      3. thank you very much, I will use SapientGuardian.EntityFrameworkCore.MySql then

        🙂

      4. “MySql.Data.EntityFrameworkCore”: “7.0.5-ir21” does not work yet

  6. Database.EnsureCreatedAsync() doesn’t seem to be implemented in SapientGuardian drivers…

  7. selom banybah · · Reply

    Thank you for this tutorial

  8. if I try to run the asp.net project I get:
    Cannot read configuration file
    Config File \\?\C:\git\damienbod\AspNet5MultipleProject\src\AspNet5MultipleProject\web.config

    where is this path baked in? I cannot find it in any configs?

    1. Hi Kunga

      The only config should be in config.json which needs to be changed to your path. Delete the project lock file, restore and rebuild. Then it should work.

      Greetings Damien

  9. […] Source: ASP.NET Core 1.0 with MySQL and Entity Framework Core […]

  10. Hello! Thanks a lot for your article!

    Can u help me to resolve some problems? I have console app, but followed your instructions as much close as I can.

    Migrations works well, but I can’t update database.

    The error is here: http://pastebin.com/cHhPBJR2

    Thanks in advance, Nick.

    1. Hi Nick, thanks is your connection string correct?

      Greetings Damien

      1. Hello again. Thanks for your response!

        You absolutely right, some parameters was left from MS SQL connection.
        Other problems was with packages. Running ‘ update-package -pre ‘ solved this.

        Now I have other problem. Trying to select data using IQueriable as method result.

        Got exception says
        Method not found: ‘Void Microsoft.EntityFrameworkCore.Query.ExpressionTranslators.Internal.EndsWithTranslator..ctor()’.

        Stack trace added in this link: http://pastebin.com/hLGejTAp

        Trying to google this give me nothing. Maybe you will have some suggestions? 🙂

        Thanks in advance, Nick.

  11. Lito Juliano · · Reply

    In this example, can apply in DB2?
    or Do you have separate sample for ASP.NET Core 1.0 with DB2 and Entity Framework Core?

    1. Hi Lito, no I never tried DB2, will look and see if I can find someting. Let me know if you find anything, would be great.

      Greetings Damien

  12. Don’t forget to add using MySQL.Data.Entity.Extensions; fo UseMySQL(

  13. Actually, that would be ‘MySQL.Data.EntityFrameworkCore.Extensions’. for the ‘UseMySQL()’ extension method.

  14. Oscar Llop · · Reply

    Hello Damien,

    Have you tried with Entity Framework Core 2.0?

    1. Hi Oscar
      No I’m updating a security module, and plan to try out 2.0 after this Greetings Damien

  15. Hi, I’m trying to run “dotnet ef database update”, but when I do it, it shows me the message Keyword not supported: ‘server’. Does someone knows about it?

  16. […] ASP.NET Core with MySQL and Entity Framework Core […]

  17. Jahan · · Reply

    I’ve applied asp.net core Identity 3.1 in my project and i want to use MySql.
    I got this error while I run Update-Database

    Failed executing DbCommand (6ms) [Parameters=[], CommandType=’Text’, CommandTimeout=’30’]
    ALTER TABLE `User` DROP INDEX `UserNameIndex`;

    more details:
    https://stackoverflow.com/questions/61765388/code-first-approach-does-not-create-tables-in-mysql-by-using-entity-framework-co

  18. I’ve applied asp.net core Identity 3.1 in my project and i want to use MySql.
    I got this error while I run Update-Database

    Failed executing DbCommand (6ms) [Parameters=[], CommandType=’Text’, CommandTimeout=’30’]
    ALTER TABLE `User` DROP INDEX `UserNameIndex`;

    more details:
    https://stackoverflow.com/questions/61765388/code-first-approach-does-not-create-tables-in-mysql-by-using-entity-framework-co

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.