Optimistic concurrency with inheritance in model first

Discussion of open issues, suggestions and bugs regarding ADO.NET provider for Oracle
Post Reply
Bonsahib
Posts: 10
Joined: Fri 04 Mar 2011 13:48

Optimistic concurrency with inheritance in model first

Post by Bonsahib » Fri 04 Mar 2011 15:25

Hi,

I have to have optimistic concurrency within my data model which inlcudes inheritance. At the moment I get too many concurrency exceptions, especially when I update a property multiple times within the same context.
Here are the steps to reproduce my problem:
Just create a very simple base entity "MyBaseObject" with three properties:
- DBKey (int, primary key, StoreGeneratedPattern = Identity)
- Name (string, allows null)
- RowsetVersion (int64, allows null, StoreGeneratedPattern = Computed, default value = 0, Concurrency Mode = Fixed)

And create an enity "MyObject" deriving from "MyBaseObject" with just one property:
- Content (string, allows null)

I chose "Table per Type" and "File per Entity" in my code generation options and generated the database from my model.
I added this trigger to the generated ddl:

CREATE OR REPLACE TRIGGER UPD_MyObjects
BEFORE UPDATE ON "MyObjects"
FOR EACH ROW
BEGIN
UPDATE "MyObjectBases" SET "RowsetVersion" = "RowsetVersion" + 1 WHERE "DBKey" = :NEW."DBKey";
END UPD_MyObjects;

I know it only handels updates on my "MyObjects"-table. But that's OK for now.

Now I run the following code:

Code: Select all

using (DataEntities entities = new DataEntities()) {
    try {
        MyObject testOrder = new MyObject();
        testOrder.Name = "Hans";
        testOrder.Content = "MyContent";
        entities.MyObjectBases.AddObject(testOrder);
        entities.SaveChanges();

        testOrder.Content = "MyNewContent";
        entities.SaveChanges();

        testOrder.Content = "MyNewExtraContent";
        entities.SaveChanges();
    }
    catch (Exception e) {

    }
}
In my case it always throws an optimistic concurrency exception.
(Btw. I have the same issue within MsSql and the .Net provider. The only way to get MsSql and Entity Framework to not throw the exception is by changing the type of RowsetVersion to timestamp in the database and to binary in my entity model)

Now my questions are:
- Is there a best practise of handling optimistic concurrency in models with inheritance?
- I guess there is no type like the built in MsSql-timestamp in Oracle for handling this concurrency issue, right?
- Any suggestions on how to deal with this?

I am really looking forward to your answers ;)

Andi

AndreyR
Devart Team
Posts: 2919
Joined: Mon 07 Jul 2008 13:16

Post by AndreyR » Thu 10 Mar 2011 16:29

You are using a correct approach. We have reproduced the problem, we are investigating the reason of it.
I will let you know about the results of our investigation.

Bonsahib
Posts: 10
Joined: Fri 04 Mar 2011 13:48

Post by Bonsahib » Mon 14 Mar 2011 08:57

Hi and thank you for investigating on this.

I did some further research on this and could condense the problem a little more. Since I guess this problem is a basic problem with inheritance and the EF you can take a look at my last post at the MSDN forum regarding the same issue: http://social.msdn.microsoft.com/Forums ... 7a0c0cd06b

Hope it helps.

Andi

AndreyR
Devart Team
Posts: 2919
Joined: Mon 07 Jul 2008 13:16

Post by AndreyR » Mon 14 Mar 2011 15:30

Thank you for the additional information, however, we have already obtained similar results in the process of our testing.

AndreyR
Devart Team
Posts: 2919
Joined: Mon 07 Jul 2008 13:16

Post by AndreyR » Fri 18 Mar 2011 15:04

We have implemented the necessary behaviour. There are some notes, however:
1. The base table should have an update trigger increasing the version column value.
2. The child table should not have this update trigger (because update of the parent table initiates the update of the child table).

Bonsahib
Posts: 10
Joined: Fri 04 Mar 2011 13:48

Post by Bonsahib » Mon 21 Mar 2011 06:45

Hi Andrey,

I modified my base-table-trigger in order to prevent it from beeing fired through the child-table-trigger:

Code: Select all

CREATE OR REPLACE
TRIGGER UPD_MYOBJECTBASE
BEFORE UPDATE OF "COLUMN1", "COLUMN2", ... (all columns except for the row version column) ON "MYOBJECTBASE" FOR EACH ROW
BEGIN
 :NEW."ROWSETVERSION" := :OLD."ROWSETVERSION" + 1;
 END;
But if you get optimistic concurrency working without the child-table-trigger, that would also be great.
Hope to hear soon about it ;)

Andi

EDIT: I tested a little and found out that the EF (randomly) changes the order of update statements. So you are absolutely right, even my modified trigger on the child-table may cause the ROWSETVERSION column to be updated twice within the same transaction. Not good! It's getting a little more tricky...

AndreyR
Devart Team
Posts: 2919
Joined: Mon 07 Jul 2008 13:16

Post by AndreyR » Thu 24 Mar 2011 13:55

We have released a new build. It can be downloaded from here (the trial version) or from Registered Users' Area (for users with active subscription only).
Detailed information about the fixes and improvements available in dotConnect for Oracle 6.10.126 is available here.
Please confirm that the problem is fixed in it.

Bonsahib
Posts: 10
Joined: Fri 04 Mar 2011 13:48

Post by Bonsahib » Fri 25 Mar 2011 13:08

Hi Andrey,

I'm impressed how fast you fixed this issue. My first tests look very good. Can't reproduce the problem with your new release. I am going to test more on monday...
Thank you very much for your fast reaction!

Andi

EDIT: All other tests are also running now. Thank you again!

Post Reply