musium
musium

Reputation: 3082

EF 6 and Oracle using Guid as primary key

In our application (ASP.NET MVC 5) we are using EF 6 code-first with SQL Server. Now we need to get it running using an Oracle DB (our customers don’t trust SQL Server).

We've managed to get a small test project working, but we have some problems migrating our real application.

One problem which we aren’t able to solve yet, is using Guid as primary key (all our classes have a Guid as primary key).

Something like:

public class TestModel
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid TestModelId { get; set; }
}

If we run Update-Database using the code above we get the following exception:

Identity-Spalte muss einen numerischen Typ aufweisen = Identity-Column must be a numeric type

Oracle.ManagedDataAccess.Client.OracleException (0x000077D3): ORA-30675: Identity-Spalte muss einen numerischen Typ aufweisen
ORA-30675: Identity-Spalte muss einen numerischen Typ aufweisen

We tried to fix this by telling Oracle/EF to make the field of type RAW(16):

protected override void OnModelCreating( DbModelBuilder modelBuilder )
{
    modelBuilder.Entity<TestModel>()
                .ToTable("TESTMODEL", "MySchema");

    modelBuilder.Entity<TestModel>()
                .Property( x => x.TestModelId )
                .HasColumnType( "RAW(16)" );
}

After running Update-Database we are getting the following exception (Not very helpful... for us at least):

System.InvalidOperationException: Sequence contains no matching element

The only which works seems to be removing the DatabaseGeneratedAttribute and the type mapping:

public class TestModel
{
     [Key]
     //[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
     public Guid TestModelId { get; set; }
}

protected override void OnModelCreating( DbModelBuilder modelBuilder )
{
    modelBuilder.Entity<TestModel>()
                .ToTable("TESTMODEL", " MySchema");

    /*modelBuilder.Entity<TestModel>()
                .Property( x => x.TestModelId )
                .HasColumnType( "RAW(16)" );*/
}

This generates a table which looks like this:

+----------------------------------+
| Name        | DataType | NotNull |
+----------------------------------+
| TestModelId | RAW(16)  | True    |
+----------------------------------+

But without the DatabaseGeneratedAttribute we have to give our models manually a primary key... which we don't want to do.

How can we use Guid as primary key with DatabaseGenerated(DatabaseGeneratedOption.Identity) using an Oracle database?

We are using:

Our configuration (web.config):

<configuration>
  <configSections>
    <section name="entityFramework"
             type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
             requirePermission="false" />
  </configSections>
  <connectionStrings>
    <add name="Model1" connectionString="DATA SOURCE=ORCL;PASSWORD=PASSWORD;PERSIST SECURITY INFO=True;USER ID=USER"
         providerName="Oracle.ManagedDataAccess.Client" />
  </connectionStrings>
  <entityFramework>
    <providers>
      <provider invariantName="Oracle.ManagedDataAccess.Client"
                type="Oracle.ManagedDataAccess.EntityFramework.EFOracleProviderServices, Oracle.ManagedDataAccess.EntityFramework, Version=6.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342" />
    </providers>
  </entityFramework>
  <system.data>
    <DbProviderFactories>
      <remove invariant="Oracle.ManagedDataAccess.Client" />

      <add name="Oracle Data Provider for .NET" description="Oracle Data Provider for .NET"
           invariant="Oracle.ManagedDataAccess.Client"
           type="Oracle.ManagedDataAccess.Client.OracleClientFactory, Oracle.ManagedDataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342" />
    </DbProviderFactories>
  </system.data>
</configuration>

Upvotes: 1

Views: 2395

Answers (1)

Ray Chen
Ray Chen

Reputation: 99

I have the similar issue and tried to use Adriano Repetti's suggestion, which is to add "Guid.NewGuid()" in the constructor. It worked perfectly!

Upvotes: 1

Related Questions