Entity Framework and multiple contexts on same database

Discussion of open issues, suggestions and bugs regarding ADO.NET provider for Oracle
Post Reply
hoekki
Posts: 8
Joined: Thu 21 Nov 2013 14:30

Entity Framework and multiple contexts on same database

Post by 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: 8
Joined: Thu 21 Nov 2013 14:30

Re: Entity Framework and multiple contexts on same database

Post by 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

Shalex
Site Admin
Posts: 9543
Joined: Thu 14 Aug 2008 12:44

Re: Entity Framework and multiple contexts on same database

Post by 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
Site Admin
Posts: 9543
Joined: Thu 14 Aug 2008 12:44

Re: Entity Framework and multiple contexts on same database

Post by 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/oracl ... story.html.

JIC
Be aware about the change starting from v9.0: viewtopic.php?t=33571 > "Entity Framework Assembly Name Change".

Post Reply