I'm using an embedded Firebird database with code first (Entity Framework 6). The first time the application runs, it works fine: the database gets created and the data gets inserted. But every time it runs after that, it throws the following exception:
An exception of type 'System.NotSupportedException' occurred in
FirebirdSql.Data.FirebirdClient.dll but was not handled in user code
Additional information: Unknown data type
The project includes the following NuGet packages:
- EntityFramework [6.0.2]
- Firebird ADO.NET Data provider (Entity Framework 6) [4.1.0.0]
I added the DbProviderFactories
and FirebirdSql.Data.FirebirdClient
provider to App.config
as described here.
I also added the Firebird DLLs to the project and set them to copy to the output directory:
- fbembed.dll
- ib_util.dll
- icudt30.dll
- icuin30.dll
- icuuc30.dll
I have not enabled code first migrations (though the __MigrationHistory
table still gets created for some reason).
Here's the code:
class Program
{
static void Main(string[] args)
{
Database.SetInitializer<FirebirdDbContext>(new CreateDatabaseIfNotExists<FirebirdDbContext>());
string connectionString = "server type=Embedded;user id=sysdba;password=masterkey;role name=RDB$ADMIN;character set=UTF8;initial catalog=test.fdb";
using (var context = new FirebirdDbContext(connectionString))
{
context.Users.Add(new User()
{ Created = DateTime.Now,
Name = "smith" });
context.SaveChanges();
}
}
}
class User
{
[Key]
public DateTime Created { get; set; }
public string Name { get; set; }
}
class FirebirdDbContext : DbContext
{
public FirebirdDbContext(string connString)
: base(new FbConnection(connString), true) { }
public DbSet<User> Users { get; set; }
}
class MyConfiguration : DbConfiguration
{
public MyConfiguration()
{
SetDefaultHistoryContext((c, s) => new SmallKeyHistoryContext(c, s));
}
}
class SmallKeyHistoryContext : HistoryContext
{
public SmallKeyHistoryContext(DbConnection existingConnection, string defaultSchema)
: base(existingConnection, defaultSchema) { }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// HACK: Make this column smaller to avoid the following error:
// key size exceeds implementation restriction for index "PK___MigrationHistory"
modelBuilder.Entity<HistoryRow>().Property(h => h.ContextKey).HasMaxLength(53).IsRequired();
}
}
The exception gets thrown on the context.Users.Add(...)
line.
Here's the stack trace:
at FirebirdSql.Data.Common.DbValue.GetBytes() in c:\Users\Jiri\Documents\devel\NETProvider\working\NETProvider\source\FirebirdSql\Data\Common\DbValue.cs:line 315
at FirebirdSql.Data.Client.Common.XsqldaMarshaler.MarshalManagedToNative(Charset charset, Descriptor descriptor) in c:\Users\Jiri\Documents\devel\NETProvider\working\NETProvider\source\FirebirdSql\Data\Client\Common\XsqldaMarshaler.cs:line 121
at FirebirdSql.Data.Client.Native.FesStatement.Execute() in c:\Users\Jiri\Documents\devel\NETProvider\working\NETProvider\source\FirebirdSql\Data\Client\Native\FesStatement.cs:line 355
at FirebirdSql.Data.FirebirdClient.FbCommand.ExecuteCommand(CommandBehavior behavior, Boolean returnsSet) in c:\Users\Jiri\Documents\devel\NETProvider\working\NETProvider\source\FirebirdSql\Data\FirebirdClient\FbCommand.cs:line 1246
at FirebirdSql.Data.FirebirdClient.FbCommand.ExecuteReader(CommandBehavior behavior) in c:\Users\Jiri\Documents\devel\NETProvider\working\NETProvider\source\FirebirdSql\Data\FirebirdClient\FbCommand.cs:line 566
at FirebirdSql.Data.FirebirdClient.FbCommand.ExecuteDbDataReader(CommandBehavior behavior) in c:\Users\Jiri\Documents\devel\NETProvider\working\NETProvider\source\FirebirdSql\Data\FirebirdClient\FbCommand.cs:line 666
at System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)
at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.<>c__DisplayClassb.<Reader>b__8()
at System.Data.Entity.Infrastructure.Interception.InternalDispatcher`1.Dispatch[TInterceptionContext,TResult](Func`1 operation, TInterceptionContext interceptionContext, Action`1 executing, Action`1 executed)
at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.Reader(DbCommand command, DbCommandInterceptionContext interceptionContext)
at System.Data.Entity.Internal.InterceptableDbCommand.ExecuteDbDataReader(CommandBehavior behavior)
at System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)
at System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior)
The stack trace points to the Firebird library (right here). I tried tracing the code backwards but I can't tell if GetBytes()
is called for all fields or just byte[]
fields. (I initially thought that it might be related to the __MigrationHistory.Model
field in the database, but the error still occurs if that table is empty. However, I don't want my speculation to cause misdirection.)
I could hack around the issue, but I'd really like to understand it. Does anyone know what's happening here?