1

I am new to entity framework and I have been searching a while for an answer to this question and I can't find anything that directally addresses this.

Here is the problem. I have a table in Oracle. In this table there are 2 fields(there are more but not important to this question). Card_Transaction_Id and Parent_Card_Transaction_ID. The Parent_Card_Transaction_Id field is constrained by the Card_Transaction_Id field and I am using a Oracle sequence via a trigger to populate the Card_Transaction_Id field.

In my code, I am using Entity Framework(Version 5) to connect using the Code First Approach.

The issue is when I try to create a new record. I need to know what the next sequence value is in order to populate the Parent_Card_Transaction_Id. My mapping for card transactions:

public class CardTransactionMap : EntityTypeConfiguration<CardTransaction>
{
    public CardTransactionMap(string schema)
    {

        ToTable("CARD_TRANSACTION", schema);

        // Mappings & Properties

        // Primary Key
        HasKey(t => t.CardTransactionId);
        Property(t => t.CardTransactionId)
            .HasColumnName("CARD_TRANSACTION_ID")
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        Property(t => t.ParentCardTransactionId)
            .HasColumnName("PARENT_CARD_TRANSACTION_ID");

        Property(t => t.CardProfileId)
            .HasColumnName("CARD_PROFILE_ID");
    }
}

The question is - is there any way to get the next sequence number before I save the record?

My current work arround is to use the following method:

    public static decimal GetNextCardTransactionSequenceValue()
    {
        using (var context = new Context(new OracleConnectionFactory().GetConnection()))
        {

            var sequence = context.Database.SqlQuery<int>("select card_transaction_id from card_transaction").ToList();

            return sequence[0];

        }   

    }

Using that method, I get the next value and then just populate my table. This works but I don't like doing it this way. I feel that there must be a better way to do it.

Thanks in advance.

ocuenca
  • 38,548
  • 11
  • 89
  • 102
kurabdurbos
  • 267
  • 1
  • 14
  • can you not create a query in Oracle that returns the next Sequence, or change the Identity field of that table to be Auto-Generated.. – MethodMan Feb 09 '15 at 19:47
  • Currently thats what I did, I have a method that gets the next sequence value. The DatabaseGenerated options do not seem to do anything with Oracle. I just hate that approach of the seperate method and figured I should be able to do with Entity - but it might be a limitation of using Oracle. – kurabdurbos Feb 09 '15 at 20:01
  • then create a trigger do you need me to show you some example code that you can refactor to work on your end..? – MethodMan Feb 09 '15 at 20:03
  • Actually the answer is here : http://stackoverflow.com/questions/11296361/how-to-create-id-with-auto-increment-on-oracle – Philip Stuyck Feb 09 '15 at 21:01
  • That would be awesome - If I was on 12c.....unfortunally I am not. We are working on a trigger combo to solve this. – kurabdurbos Feb 09 '15 at 21:16

3 Answers3

2

You have to do this by navigation properties.

By fetching the next value from a sequence before actually using it in the same session you create yourself a concurrency issue: another user can increment the index (by an insert) in the time between drawing its next value and assigning it to the child record. Now the child will belong to the other user's record!

If your CardTransaction class has a parent reference like this:

int ParentCardTransaction { get; set; }

[ForeignKey("ParentCardTransaction")]
CardTransaction ParentCardTransaction { get; set; }

you can create a parent and child in one go and call SaveChanges without worrying about setting FK values yourself:

var parent = new CardTransaction { ... };
var child = new CardTransaction { ParentCardTransaction = parent, ... };
SaveChanges();

Now EF wil fetch the new CardTransactionId from the parent and assign it to the FK of the child. So generating and getting the parent Id happens all in one session, so it is guaranteed to be the same value.

Apart from preventing concurrency issues, of course it is much easier anyway to let EF do the heavy lifting of getting and assiging key values.

Gert Arnold
  • 105,341
  • 31
  • 202
  • 291
0

Create a Stored Procedure or Query that will return you the next Value from the Table here is an Example

SELECT NVL(MAX(card_transaction_id + 1), 0) AS MAX_VAL
FROM card_transaction T;

or Create a Trigger - for OracleDB

Create A Trigger to Return Next Id

MethodMan
  • 18,625
  • 6
  • 34
  • 52
0

Change your table definition to this :

CREATE TABLE t1 (c1 NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY, 
               c2 VARCHAR2(10));

as per the information in the link i provided in the comment. after the update ef will automatically query the value for the id that is inserted, there is no need to fill in the id before the insert. ef will generate an insert sql query without id.

Philip Stuyck
  • 7,344
  • 3
  • 28
  • 39
  • My understanding is this works with Oracle 12c and above - I am using 11gR2 so I don't think this will work in this case. – kurabdurbos Feb 09 '15 at 21:17
  • If you read the link i provided then there is also a soluton involving triggers to get your id filled in using a sequence. The trigger basically makes it behave like an identity column. – Philip Stuyck Feb 10 '15 at 07:37