2

Using EfCore 2.2.4 I am attempted to override the base DbSet implementation in one of my Db Contexts.

I am using Oracle.ManagedDataAccess.Core 2.18.6 and if I try to call context.Customer.Add(new Customer()); (All fields in customer are nullable for arguments sake except the primary key RECORDNO) I get the error:

cannot insert NULL into (SCHEMA.CUSTOMER.RECORDNO).

I realise I need to work out and add the RECORDNO sequence value to the entity before I commit changes via EfCore and wanted to do this by extending DbSet.Add as follows:

public class OracleDbContext : DbContext
{
    public class OracleDbSet<TEntity> : DbSet<TEntity> where TEntity : class
    {
        public override EntityEntry<TEntity> Add(TEntity entity)
        {
            SetEntityRecordNumber(entity); //this will use reflection for [Key] attribute and set it to a sequence value I collect from the database
            return base.Add(entity);
        }
    }

    public OracleDbSet<Customer> Customers { get; set; }
...

However when I now call context.Customer.Add(new Customer()); the value is null for context.Customer.

How do I properly get the DbContext to register instances of OracleDbContext aswell as DbContext, or is there a simpler and still generic way of achieving an override or extension to DbContext.Add()?

Ben Maxfield
  • 635
  • 7
  • 21
  • There's no reason to extend `Add`. What you ask is specific to each individual *entity*. The obvious fix is to add the key in the application code. A better option would be to mark the primary key properties as database-generated with the [DatabaseGenerated](https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.dataannotations.schema.databasegeneratedattribute.databasegeneratedoption?view=netframework-4.8) with an option of Identity, and set the sequence value as a default or an INSERT trigger in the database – Panagiotis Kanavos May 08 '19 at 08:35
  • @IvanStoev only if the provider implements them though. Oracle's ADO.NET/EF providers are known for their size and overhead, not their feature completeness. – Panagiotis Kanavos May 08 '19 at 08:43
  • [EF Core already supports sequences](https://learn.microsoft.com/en-us/ef/core/modeling/relational/sequences) as long as the provider implements them. [This probably duplicate question](https://stackoverflow.com/questions/48072734/how-to-generate-and-auto-increment-id-with-ef-core-oracle) shows that at least dotConnect implements them – Panagiotis Kanavos May 08 '19 at 08:48
  • @PanagiotisKanavos It is indeed individual to each entity, I see your point, however I didn't want to modify the database if I can avoid it hence not using a trigger in the DB. @IvanStoev I don't have access to the `.HasSequence` extension as I don't think the Oracle EF provider I am using it has implemented it. Outside of the actual points made here and my given reason for wanting to do it how would you extend DbSet if you wanted to for any other reason? – Ben Maxfield May 08 '19 at 08:49
  • @PanagiotisKanavos *"Oracle's ADO.NET/EF providers are known for their size and overhead, not their feature completeness."* Indeed (unfortunately). – Ivan Stoev May 08 '19 at 08:52
  • @BenMaxfield I'm not sure `DbSet` is intended to be extended (although apparently it allows that). But note that most of the `DbSet` methods (except `IQueryable` related) are actually implemented by the `DbContext`, so you might consider overriding `Add` methods there. Or implementing custom `ValueGenerator`. – Ivan Stoev May 08 '19 at 08:56

0 Answers0