Entity Framework and multiple contexts on same database

Entity Framework and multiple contexts on same database

Postby hoekki » Thu 04 Feb 2016 17:15

Hi everyone,

I stumbled upon what seems to be a bug in devart dotConnect for oracle. I am using entity framework in my application, having currently 2 separate contexts, in separate assemblies. When I create the databases, the first is created without problems, however, the second one crashes. Debugging with DbMonitor led me to the _MigrationHistory table. It seems, dotConnect tries to create the whole table again, which of course fails. Also it fails to register the second context in the _MigrationHistory table, so concerning migrations, the second context is broken. All other tables of the second context are created correctly, however.

I get the following output on the creation of the second context:
Code: Select all
-- Table "__MigrationHistory"
CREATE TABLE "__MigrationHistory" (
  "MigrationId" NVARCHAR2(150) NOT NULL,
  "ContextKey" NVARCHAR2(300) NOT NULL,
  "Model" BLOB NOT NULL,
  "ProductVersion" NVARCHAR2(32) NOT NULL,
  CONSTRAINT "PK___MigrationHistory" PRIMARY KEY ("MigrationId", "ContextKey")
)

which fails, as it already exists. With a nice ORA-00955 Exception.
Right after, I get another error, Entity Framework executing the following query:
SELECT
"top"."Id",
"top"."ModelHash"
FROM ( SELECT
"Extent1"."Id",
"Extent1"."ModelHash"
FROM "EdmMetadata" "Extent1"
ORDER BY "Extent1"."Id" DESC
) "top"
WHERE ROWNUM <= 1

If I ignore all these exceptions, The program works well, as all the tables are there. But I also need migrations, and that is hindered by the messed up _MigrationHistory table.

Tried this on a SqlServer, working quite well.

Of course I could use ContextKey to add a prefix for the tables, creating two separate migration history tables, one for each context. But I rather not have to fall back to that workaround, as in oracle, name lengths are already forced to be short as is.

Edit: It works if I disable and delete migrations on both contexts. Now both context share the same MigrationHistory table and everything works fine. Well, except the migrations :( So this hickup only occurs with multiple contexts AND migrations.


Best regards


PS: using EF 6.1.3, dotConnect 8.5.506
hoekki
 
Posts: 6
Joined: Thu 21 Nov 2013 14:30

Re: Entity Framework and multiple contexts on same database

Postby hoekki » Mon 08 Feb 2016 14:33

Edit: I did some more testing. It looks like dotConnect does not support multiple contexts at all.
--- Assembly AssemblyA ---
A.cs
Code: Select all
public class A
{
   public int Id{get;set;}
}


ContextA.cs
Code: Select all
[DbConfigurationType(typeof(MyConfiguration)]
public class ContextA : DbContext
{
   public DbSet<A> As{get;set;}
   protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Configurations.Add(new AMap());
        }
}


AMap.cs
Code: Select all
class AMap : EntityTypeConfiguration<A>
{
   public AMap(
   {
      ToTable("As");
      HasKey(x=>x.Id);
   }
}


--- Assembly AssemblyB ---
B.cs
Code: Select all
public class B
{
   public int Id{get;set;}
}


ContextB.cs
Code: Select all
[DbConfigurationType(typeof(MyConfiguration)]
public class ContextB : DbContext
{
   public DbSet<B> Bs{get;set;}
   protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Configurations.Add(new BMap());
        }
}


BMap.cs
Code: Select all
class BMap : EntityTypeConfiguration<B>
{
   public BMap(
   {
      ToTable("Bs");
      HasKey(x=>x.Id);
   }
}


--- Assembly Configuration ---
MyConfiguration.cs
Code: Select all
public class MyConfiguration : DbConfiguration
{
   public MyConfiguration()
   {
      var _ = typeof (System.Data.Entity.SqlServer.SqlProviderServices);
      var __ = typeof (System.Data.Entity.SqlServerCompact.SqlCeProviderServices);
      SetProviderServices("Devart.Data.Oracle", OracleEntityProviderServices.Instance);
      var conf = OracleEntityProviderConfig.Instance;
      conf.CodeFirstOptions.ColumnTypeCasingConventionCompatibility = true;
      conf.DmlOptions.BatchUpdates.Enabled = true;
      conf.Workarounds.IgnoreSchemaName = true;
      conf.DatabaseScript.Schema.DeleteDatabaseBehaviour = DeleteDatabaseBehaviour.AllSchemaObjects;
      conf.QueryOptions.CaseInsensitiveComparison = true;
      conf.QueryOptions.CaseInsensitiveLike = true;

      SetProviderServices(System.Data.Entity.SqlServer.SqlProviderServices.ProviderInvariantName,
         System.Data.Entity.SqlServer.SqlProviderServices.Instance);

      SetProviderServices(System.Data.Entity.SqlServerCompact.SqlCeProviderServices.ProviderInvariantName,
         System.Data.Entity.SqlServerCompact.SqlCeProviderServices.Instance);
   }
}


If you compile this and create the databases in a test, initiation of the second context always fails on oracle, however runs without errors on SqlServer and SqlCe. You'll get the ORA-00955 Exception on __MigrationHistory, as I mentioned above.

Please have a look into this.

Best Regards
hoekki
 
Posts: 6
Joined: Thu 21 Nov 2013 14:30

Re: Entity Framework and multiple contexts on same database

Postby Shalex » Tue 09 Feb 2016 15:53

Please send us a small test project with the corresponding DDL/DML script so that we can reproduce a scenario which works with System.Data.SqlClient but fails with Devart.Data.Oracle.
Shalex
Devart Team
 
Posts: 7602
Joined: Thu 14 Aug 2008 12:44

Re: Entity Framework and multiple contexts on same database

Postby Shalex » Fri 27 Jan 2017 13:50

The bug with creating database objects in the same schema by several EF6 contexts in Code-First approach is fixed in v9.2.162: https://www.devart.com/dotconnect/oracle/revision_history.html.

JIC
Be aware about the change starting from v9.0: http://forums.devart.com/viewtopic.php?t=33571 > "Entity Framework Assembly Name Change".
Shalex
Devart Team
 
Posts: 7602
Joined: Thu 14 Aug 2008 12:44


Return to dotConnect for Oracle