Description:
When trying to use Entity Framework 6 Code First with entities that have as Primary Keys / Foreign Keys unsigned values, an error occurs. It seems to work only for signed types for PKs / FKs.
This applies to all Connector/NET versions like 6.8.3, 6.9.2, etc.
How to repeat:
As sample:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Entity;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using MySql.Data.Entity;
using System.Data.Entity.Migrations;
using System.Data.Entity.Migrations.History;
using System.Data.Common;
namespace EF6UnitOfWorkPattern
{
public class Program
{
static void Main(string[] args)
{
using (QuoteDBContext ctx = new QuoteDBContext())
{
ctx.Database.Delete();
ctx.Database.CreateIfNotExists();
var client = new Client();
ctx.Clients.Add(client);
var quote = new Quote();
quote.Client = client;
ctx.Quotes.Add(quote);
ctx.SaveChanges();
}
}
}
[DbConfigurationType(typeof(MySqlEFConfiguration))]
public class QuoteDBContext : DbContext
{
public DbSet<Quote> Quotes { get; set; }
public DbSet<Client> Clients { get; set; }
public QuoteDBContext()
{
Database.SetInitializer<QuoteDBContext>(new QuoteDBInitialize());
Database.SetInitializer<QuoteDBContext>(new MigrateDatabaseToLatestVersion<QuoteDBContext, Configuration<QuoteDBContext>>());
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Configurations.AddFromAssembly(System.Reflection.Assembly.GetExecutingAssembly());
}
}
public class QuoteDBInitialize : DropCreateDatabaseReallyAlways<QuoteDBContext>
{
protected override void Seed(QuoteDBContext ctx)
{
base.Seed(ctx);
}
}
/// <summary>
/// This initializer really drops the database, not just once per AppDomain (like the DropCreateDatabaseAlways).
/// </summary>
/// <typeparam name="TContext"></typeparam>
public class DropCreateDatabaseReallyAlways<TContext> : IDatabaseInitializer<TContext> where TContext : DbContext
{
public void InitializeDatabase(TContext context)
{
context.Database.Delete();
context.Database.CreateIfNotExists();
this.Seed(context);
context.SaveChanges();
}
protected virtual void Seed(TContext context)
{
}
}
public class MyHistoryContext : MySqlHistoryContext
{
public MyHistoryContext(DbConnection existingConnection, string defaultSchema)
: base(existingConnection, defaultSchema)
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<HistoryRow>().ToTable("__MySqlMigrations");
modelBuilder.Entity<HistoryRow>().Property(h => h.MigrationId).HasColumnName("_MigrationId");
modelBuilder.Entity<HistoryRow>().Property(h => h.ContextKey).HasColumnName("_ContextKey");
modelBuilder.Entity<HistoryRow>().Property(h => h.Model).HasColumnName("_Model");
modelBuilder.Entity<HistoryRow>().Property(h => h.ProductVersion).HasColumnName("_ProductVersion");
}
}
public class Configuration<TContext> : DbMigrationsConfiguration<TContext> where TContext : DbContext
{
public Configuration()
{
CodeGenerator = new MySqlMigrationCodeGenerator();
AutomaticMigrationsEnabled = true;
SetSqlGenerator("MySql.Data.MySqlClient", new MySql.Data.Entity.MySqlMigrationSqlGenerator());
SetHistoryContextFactory("MySql.Data.MySqlClient", (existingConnection, defaultSchema) => new MyHistoryContext(existingConnection, defaultSchema));
}
}
public class Client
{
[Key]
public long Id { get; set; }
}
public class Quote
{
[Column("Id")]
[Key]
public long Id { get; set; }
[Column("Client")]
[ForeignKey("Client")]
public long ClientId { get; set; }
public virtual Client Client { get; set; }
}
}
And as App.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<entityFramework codeConfigurationType="MySql.Data.Entity.MySqlEFConfiguration, MySql.Data.Entity.EF6">
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="v11.0" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6" />
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
<connectionStrings>
<add name="QuoteDBContext" connectionString="***" providerName="MySql.Data.MySqlClient" />
</connectionStrings>
</configuration>
An error with this Stacktrace happens:
EF6UnitOfWorkPatternEF6CodeFirstMySqlConsoleApp.Client: : EntityType 'Client' has no key defined. Define the key for this EntityType.
EF6UnitOfWorkPatternEF6CodeFirstMySqlConsoleApp.Quote: : EntityType 'Quote' has no key defined. Define the key for this EntityType.
Clients: EntityType: EntitySet 'Clients' is based on type 'Client' that has no keys defined.
Quotes: EntityType: EntitySet 'Quotes' is based on type 'Quote' that has no keys defined.
at System.Data.Entity.Core.Metadata.Edm.EdmModel.Validate()
at System.Data.Entity.DbModelBuilder.Build(DbProviderManifest providerManifest, DbProviderInfo providerInfo)
at System.Data.Entity.DbModelBuilder.Build(DbConnection providerConnection)
at System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext)
at System.Data.Entity.Internal.RetryLazy`2.GetValue(TInput input)
at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
at System.Data.Entity.Internal.InternalContext.CreateObjectContextForDdlOps()
at System.Data.Entity.Database.Delete()
at EF6UnitOfWorkPatternEF6CodeFirstMySqlConsoleApp.Program.Main(String[] args) in c:\Users\Fito\Documents\Visual Studio 2013\Projects\EF6CodeFirstMySqlConsol
eApp\EF6CodeFirstMySqlConsoleApp\Program.cs:line 23
Press any key to continue . . .
If the types are change from ulong to long, it works fine.