I’ve been working on learning ASP.NET 5 the last few weeks. I like it. It feels like a solid platform, and I especially like Visual Studio Code. I’m discovering a few quirks, though, as is common when you’re learning a new thing. This one in particular, how to add the MySQL connector to a project, I wanted to share the solution I found.
If you were using Visual Studio proper, it’d be straightforward to use the 「manage packages」 dialog to find and add the MySQL connector. Visual Studio Code, however, doesn’t provide that dialog. The way you can add MySQL, then, is by opening up project.json and finding the 「dependencies」 block. Add a line for MySQL:
"dependencies": { ... "MySql.Data": "6.9.8" }, |
And then scroll down and find the 「frameworks」 block. I removed the entry for 「dnxcore50」 and set up the entry for 「dnx451」 like so:
"frameworks": { "dnx451": { "frameworkAssemblies": { "System.Data": "4.0.0.0" } } }, |
You’ll want to be sure to rerun dnu restore as needed. After that, your new MySqlConnection(); and dbh.Open(); statements should work as normal.
Hope this helps,
Steve
Blog
Using Entity Framework 6 and MySQL on ASP.NET 5 (vNext)
Visual Studio 2015 was recently released, and with it came a newer beta of ASP.NET 5 (formerly referred to as "ASP.NET vNext"). ASP.NET 5 is a complete rewrite of ASP.NET, focusing on being lightweight, composible, and cross-platform. It also includes an alpha version of Entity Framework 7. However, EF7 is not yet production-ready and does not support all features of EF6. One feature that is missing from EF6 is support for other database providers - Only SQL Server and SQLite are supported at this time.
I wanted to transition a site over to ASP.NET 5, but needed to continue using MySQL as a data source. This meant getting Entity Framework 6 running on ASP.NET 5, which is pretty much undocumented right now. All the documentation and tutorials for EF6 heavily relies on configuration in Web.config, which no longer exists in ASP.NET 5. In this post I'll discuss the steps I needed to take to get it running. An example project containing all the code in this post can be found at https://github.com/Daniel15/EFExample.
Since EF6 does not support .NET Core, we need to remove .NET Core support (delete "dnxcore50": { }
from project.json
). Once that's done, install the EntityFramework and MySql.Data.Entity packages, and add references to System.Data and System.Configuration. For this post, I'll be using this basic model and DbContext
, and assume you've already created your database in MySQL:
1
2
3
4
5
6
7
8
9
10
11
12
|
public
class
MyContext : DbContext
{
public
virtual
DbSet<Post> Posts {
get
;
set
; }
}
public
class
Post
{
public
int
Id {
get
;
set
; }
public
string
Title {
get
;
set
; }
public
string
Content {
get
;
set
; }
}
|
Entity Framework 6 relies on the provider and connection string being configured in Web.config. Since Web.config is no longer used with ASP.NET 5, we need to use code-based configuration to configure it instead. To do so, create a new class that inherits fromDbConfiguration
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
public
class
MyDbConfiguration : DbConfiguration
{
public
MyDbConfiguration()
{
// Attempt to register ADO.NET provider
try
{
var dataSet = (DataSet)ConfigurationManager.GetSection(
"system.data"
);
dataSet.Tables[0].Rows.Add(
"MySQL Data Provider"
,
".Net Framework Data Provider for MySQL"
,
"MySql.Data.MySqlClient"
,
typeof
(MySqlClientFactory).AssemblyQualifiedName
);
}
catch
(ConstraintException)
{
// MySQL provider is already installed, just ignore the exception
}
// Register Entity Framework provider
SetProviderServices(
"MySql.Data.MySqlClient"
,
new
MySqlProviderServices());
SetDefaultConnectionFactory(
new
MySqlConnectionFactory());
}
}
|
The first part of the configuration is a hack to register the ADO.NET provider at runtime, by dynamically adding a new configuration entry to the system.data
section. The second part registers the Entity Framework provider. We also need to modify the configuration file to include the connection string. You can use any configuration provider supported by ASP.NET 5, I'm using config.json
here because it's the default provider.
1
2
3
4
5
6
7
8
|
{
"Data"
: {
"DefaultConnection"
: {
"ConnectionString"
:
"Server=localhost; Database=test; Uid=vmdev; Pwd=password;"
}
}
}
|
Now that we have the configuration, we need to modify the context to use it:
1
2
3
4
5
6
7
8
9
10
|
[DbConfigurationType(
typeof
(MyDbConfiguration))]
public
class
MyContext : DbContext
{
public
MyContext(IConfiguration config)
:
base
(config.Get(
"Data:DefaultConnection:ConnectionString"
))
{
}
// ...
}
|
An instance of IConfiguration
will be automatically passed in by ASP.NET 5's dependency injection system. The final step is to registerMyContext
in the dependency injection container, which is done in your Startup.cs
file:
1
2
3
4
5
6
|
public
void
ConfigureServices(IServiceCollection services)
{
// ...
services.AddScoped<MyContext>();
}
|
AddScoped
specifies that one context should be created per request, and the context will automatically be disposed once the request ends. Now that all the configuration is complete, we can use MyContext
like we normally would:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public
class
HomeController : Controller
{
private
readonly
MyContext _context;
public
HomeController(MyContext context)
{
_context = context;
}
public
IActionResult Index()
{
return
View(_context.Posts);
}
}
|
Hope you find this useful!
Until next time,
— Daniel
Using EF6 with ASP.NET MVC Core 1.0 (aka MVC 6)
This week Microsoft announced that it is renaming ASP.NET 5 to ASP.NET Core 1.0. In general I think this is a very good step. Incrementing the version number from 4 to 5 for ASP.NET gave the impression that ASP.NET 5 was a continuation of the prior version and that a clean migration path would exist for upgrading apps from ASP.NET 4 to 5. However, this did not reflect the reality that ASP.NET 5 was a completely different animal, re-written from the ground up, and that is has little to do architecturally with its predecessor. I would even go so far as to say it has more in common with node.js than with ASP.NET 4.
You can download the code for this post from my Demo.AspNetCore.EF6 repository on GitHub.
Entity Framework 7, however, has even less in common with its predecessor than does MVC, making it difficult for developers to figure out whether and when they might wish to make the move to the new data platform. In fact, EF Core 1.0 is still a work in progress and won’t reach real maturity until well after initial RTM. So I’m especially happy that EF 7 has been renamed EF Core 1.0, and also that MVC 6 is now named MVC Core 1.0.
The problem I have with the name ASP.NET Core is that it implies some equivalency with .NET Core. But as you see from the diagram below, ASP.NET Core will not only runcross-platform on .NET Core, but you can also target Windows with .NET Framework 4.6.
Note: This diagram has been updated to reflect that EF Core 1.0 (aka EF 7) is part of ASP.NET Core 1.0 and can target either .NET 4.6 or .NET Core.
It is extremely important to make this distinction, because there are scenarios in which you would like to take advantage of the capabilities of ASP.NET Core, but you’ll need to run on .NET 4.6 in order to make use of libraries that are not available on .NET Core 1.0.
So why would you want to use ASP.NET Core 1.0 and target .NET 4.6?
As I wrote in my last post, WCF Is Dead and Web API Is Dying – Long Live MVC 6, you should avoid using WCF for greenfield web services, because: 1) is it not friendly to dependency injection, 2) it is overly complicated and difficult to use properly, 3) it was designed primarily for use with SOAP (which has fallen out of favor), and 4) because Microsoft appears to not be investing further in WCF. I also mentioned you should avoid ASP.NET Web API because it has an outdated request pipeline, which does not allow you to apply cross-cutting concerns, such as logging or security, across multiple downstream web frameworks (Web API, MVC, Nancy, etc). OWIN and Katana were introduced in order to correct this deficiency, but those should be viewed as temporary remedies prior to the release of ASP.NET Core 1.0, which has the same pipeline model as OWIN.
The other important advantage of ASP.NET Core is that it completely decouples you from WCF, IIS and System.Web.dll. It was kind of a dirty secret that under the covers ASP.NET Web API used WCF for self-hosting, and you would have to configure the WCF binding if you wanted implement things like transport security. ASP.NET Core has a more flexible hosting model that has no dependence on WCF or System.Web.dll (which carries significant per-request overhead), whether you choose to host in IIS on Windows, or cross-platform in Kestrel on Windows, Mac or Linux.
A good example of why you would want to use ASP.NET Core 1.0 to target .NET 4.6 would be the ability to use Entity Framework 6.x. The first release of EF Core, for example, won’t include TPC inheritance or M-M relations without extra entities. As Rowan Miller, a program manager on the EF team, stated:
We won’t be pushing EF7 as the ‘go-to release’ for all platforms at the time of the initial release to support ASP.NET 5. EF7 will be the default data stack for ASP.NET 5 applications, but we will not recommend it as an alternative to EF6 in other applications until we have more functionality implemented.
This means if you are building greenfield web services, but still require the full capabilities of EF 6.x, you’ll want to use ASP.NET MVC Core 1.0 (aka MVC 6) to create Web API’s which depend on .NET 4.6 (by specifying 「dnx451」 in the project.json file). This will allow you to add a dependency for the 「EntityFramework」 NuGet package version 「6.1.3-*」. The main difference is that you’ll probably put your database connection string in an*.json file rather than a web.config file, or you may specify it as an environment variable or retrieve it from a secrets store. An appsettings.json file, for example, might contain a connection string for a local database file.
1
2
3
4
5
6
7
|
{
"Data"
: {
"SampleDb"
: {
"ConnectionString"
:
"Data Source=(localdb)\\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\\SampleDb.mdf;Integrated Security=True; MultipleActiveResultSets=True"
}
}
}
|
You can then register your DbContext-derived class with the dependency injection system of ASP.NET Core.
1
2
3
4
5
6
7
8
9
10
11
12
|
public
void
ConfigureServices(IServiceCollection services)
{
// Add DbContext
services.AddScoped(provider =>
{
var
connectionString = Configuration[
"Data:SampleDb:ConnectionString"
];
return
new
SampleDbContext(connectionString);
});
// Add framework services.
services.AddMvc();
}
|
This will allow you to inject a SampleDbContext into the constructor of any controller in your app.
1
2
3
4
5
6
7
8
9
|
[Route(
"api/[controller]"
)]
public
class
ProductsController : Controller
{
private
readonly
SampleDbContext _dbContext;
public
ProductsController(SampleDbContext dbContext)
{
_dbContext = dbContext;
}
|
Lastly, you’ll need to provide some information to EF regarding the provider you’re using (for example, SQL Server, Oracle, MySQL, etc). In a traditional ASP.NET 4.6 app you would have done that in app.config or web.config. But in ASP.NET Core you’ll want to specify the provider in a class that inherits from DbConfiguration.
1
2
3
4
5
6
7
|
public
class
DbConfig : DbConfiguration
{
public
DbConfig()
{
SetProviderServices(
"System.Data.SqlClient"
, SqlProviderServices.Instance);
}
}
|
Then you can apply a DbConfigurationType attribute to your DbContext-derived class, so that EF can wire it all together.
1
2
3
4
5
6
7
8
|
[DbConfigurationType(
typeof
(DbConfig))]
public
class
SampleDbContext : DbContext
{
public
SampleDbContext(
string
connectionName) :
base
(connectionName) { }
public
DbSet Products {
get
;
set
; }
}
|
You can download the code for this post from my Demo.AspNetCore.EF6 repository on GitHub.
The primary limitation of targeting .NET 4.6 with EF 6 is that you’ll only be able to deploy your web services on Windows. The good news, however, is that you’ll be in a great position to migrate from EF 6 to EF Core 1.0 (aka EF 7) as soon as it matures enough to meet your needs. That’s because the API’s for EF Core are designed to be similar to EF 6. Then when you do move to EF Core, you’ll be able to use Docker to deploy your web services on Linux VM’s running in a Cloud service such as Amazon EC2, Google Compute Engine, or Microsoft Azure.