Concurrency Example

Posts   
 
    
Hugh
User
Posts: 13
Joined: 12-Mar-2009
# Posted on: 27-Mar-2009 16:20:08   

Hi,

I’ve been trying to get a concurrency example working. Below I fetch the BankAccounts entity, pause the code with a breakpoint, update the record independently with a different sql login. I then run on the code it goes into the CreatePredicate routine (twice for some reason) and seems to create it. The code runs on and saves the updated entity successfully even though I expect it to fail. There are no triggers on the BankAccounts table.

My Configuration • Post the LLBLGen Pro version + buildnr. 2.6 Final Oct 6 2008 • When it's a problem occuring at runtime, post the Runtime library version. N/A • When an exception is thrown, post the stacktrace. N/A • Post the template group + .NET version you're using. VB.Net, Adapter, VS2008, .net framework 3.5 • Post the database type and version you're using. SQL Express 2005 • Post real code See Below • Explain inheritance hierachies. N/A • If you're using custom made templates, please explain these as well. N/A

I must be missing something obvious here.

Thanks in advance. Hugh

Here is the code

Private Sub SimpleButton1_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SimpleButton1.Click

    Dim obank As New BankAccountsEntity
    Dim bRet As Boolean

    obank.BankAccId = 140
    Using odap As New DataAccessAdapter(FASDatabase.ClientDBConnectionString)

'Fetch the bank and I check the timestamp – consistent with db as expected odap.FetchEntity(obank)

        'I put a Breakpoint here on obank.AccName = "test 4"
        'Under a different sql login I update the Bank Account record for 140 – timestamp in db gets updated.
        obank.AccName = "test 4"
    'I am expecting the Update to fail because during the SaveEntity it calls the CreatePredicate 
        bRet = odap.SaveEntity(obank, True)
    'SaveEntity returns true and db updated with AccName = "test 3" and timestamp gets updated
    End Using


End Sub

Option Strict Off Imports SD.LLBLGen.Pro.ORMSupportClasses Imports FAS.HelperClasses

Public Class Concurrency ' VB.NET <DependencyInjectionInfo(GetType(IEntity2), "ConcurrencyPredicateFactoryToUse"), Serializable()> _ Public Class GeneralConcurrencyPredicateFactory Implements IConcurrencyPredicateFactory

    Public Function CreatePredicate(ByVal predicateTypeToCreate As ConcurrencyPredicateType, _
     ByVal containingEntity As Object) As IPredicateExpression Implements _
      IConcurrencyPredicateFactory.CreatePredicate


        Dim toReturn As IPredicateExpression = New PredicateExpression()

Dim bankacc As FAS.EntityClasses.BankAccountsEntity = CType(containingEntity, FAS.EntityClasses.BankAccountsEntity)

        Select Case predicateTypeToCreate
            Case ConcurrencyPredicateType.Delete


            Case ConcurrencyPredicateType.Save
                ' only for updates
                toReturn.Add(BankAccountsFields.TimeStamp = _
                  bankacc.Fields("TimeStamp").DbValue)

        End Select
    End Function

End Class

End Class

MTrinder
User
Posts: 1461
Joined: 08-Oct-2008
# Posted on: 31-Mar-2009 21:46:17   

Please can you post the SQL generated when you run the update from the code - it may give us an idea of what is going on...

Matt

Hugh
User
Posts: 13
Joined: 12-Mar-2009
# Posted on: 01-Apr-2009 12:34:36   

Thanks Matt. How do I go about getting to the sql query generated?

Walaa avatar
Walaa
Support Team
Posts: 14983
Joined: 21-Aug-2005
# Posted on: 01-Apr-2009 16:01:33   
Hugh
User
Posts: 13
Joined: 12-Mar-2009
# Posted on: 17-Apr-2009 15:42:05   

Thanks for that. I've come back to this and turned on the trace and the trace output is below. The sql is consistent with what is happening but I expected the where clause to have made reference to the timestamp created in the GeneralConcurrencyPredicateFactory. Have I the syntax wrong for this. As mentioned as part of saveentity it goes into the concurrency CreatePredicate routine?

By the way why are the queries generated twice?

Method Enter: CreateUpdateDQ(4) Method Enter: CreateUpdateDQ(4) Method Enter: CreateSingleTargetUpdateDQ(4) Method Enter: CreateSingleTargetUpdateDQ(4) Generated Sql query: Query: UPDATE [MPVLocal].[dbo].[BankAccounts] SET [AccName]=@AccName WHERE ( [MPVLocal].[dbo].[BankAccounts].[Bank_Acc_ID] = @BankAccId1) Parameter: @AccName : String. Length: 200. Precision: 0. Scale: 0. Direction: Input. Value: "test 4". Parameter: @BankAccId1 : Int16. Length: 0. Precision: 5. Scale: 0. Direction: Input. Value: 140.

Generated Sql query: Query: UPDATE [MPVLocal].[dbo].[BankAccounts] SET [AccName]=@AccName WHERE ( [MPVLocal].[dbo].[BankAccounts].[Bank_Acc_ID] = @BankAccId1) Parameter: @AccName : String. Length: 200. Precision: 0. Scale: 0. Direction: Input. Value: "test 4". Parameter: @BankAccId1 : Int16. Length: 0. Precision: 5. Scale: 0. Direction: Input. Value: 140.

Method Exit: CreateSingleTargetUpdateDQ(4) Method Exit: CreateSingleTargetUpdateDQ(4) Method Exit: CreateUpdateDQ(4) Method Exit: CreateUpdateDQ(4)

MTrinder
User
Posts: 1461
Joined: 08-Oct-2008
# Posted on: 21-Apr-2009 21:38:04   

Using SQL profiler, can you see the actual SQL that is hitting the db server - I just want to check that you are not recording something in the trace that is generated before the concurrency predicate sql is injected into it.

Matt

Hugh
User
Posts: 13
Joined: 12-Mar-2009
# Posted on: 23-Apr-2009 15:27:04   

Hi Matt,

Yes here is the profiler for running the update routine - it makes no reference to the timestamp in the sql.disappointed

exec sp_reset_connection go exec sp_executesql N'SELECT [MPVLocal].[dbo].[BankAccounts].[Bank_Acc_ID] AS [BankAccId], [MPVLocal].[dbo].[BankAccounts].[BankID] AS [BankId], [MPVLocal].[dbo].[BankAccounts].[AccName], [MPVLocal].[dbo].[BankAccounts].[AccNumber], [MPVLocal].[dbo].[BankAccounts].[SortCode], [MPVLocal].[dbo].[BankAccounts].[IBankTempCode] AS [IbankTempCode], [MPVLocal].[dbo].[BankAccounts].[BankTransID] AS [BankTransId], [MPVLocal].[dbo].[BankAccounts].[RecRequired], [MPVLocal].[dbo].[BankAccounts].[InternalAccount], [MPVLocal].[dbo].[BankAccounts].[CurrencyID] AS [CurrencyId], [MPVLocal].[dbo].[BankAccounts].[DaysForInterestRate], [MPVLocal].[dbo].[BankAccounts].[ShortDesc], [MPVLocal].[dbo].[BankAccounts].[NotionalAccount], [MPVLocal].[dbo].[BankAccounts].[TimeStamp] FROM [MPVLocal].[dbo].[BankAccounts] WHERE ( ( [MPVLocal].[dbo].[BankAccounts].[Bank_Acc_ID] = @BankAccId1))',N'@BankAccId1 smallint',@BankAccId1=140 go exec sp_reset_connection go exec sp_executesql N'UPDATE [MPVLocal].[dbo].[BankAccounts] SET [AccName]=@AccName WHERE ( [MPVLocal].[dbo].[BankAccounts].[Bank_Acc_ID] = @BankAccId1)',N'@AccName nvarchar(200),@BankAccId1 smallint',@AccName=N'test 55',@BankAccId1=140go exec sp_executesql N'SELECT [MPVLocal].[dbo].[BankAccounts].[Bank_Acc_ID] AS [BankAccId], [MPVLocal].[dbo].[BankAccounts].[BankID] AS [BankId], [MPVLocal].[dbo].[BankAccounts].[AccName], [MPVLocal].[dbo].[BankAccounts].[AccNumber], [MPVLocal].[dbo].[BankAccounts].[SortCode], [MPVLocal].[dbo].[BankAccounts].[IBankTempCode] AS [IbankTempCode], [MPVLocal].[dbo].[BankAccounts].[BankTransID] AS [BankTransId], [MPVLocal].[dbo].[BankAccounts].[RecRequired], [MPVLocal].[dbo].[BankAccounts].[InternalAccount], [MPVLocal].[dbo].[BankAccounts].[CurrencyID] AS [CurrencyId], [MPVLocal].[dbo].[BankAccounts].[DaysForInterestRate], [MPVLocal].[dbo].[BankAccounts].[ShortDesc], [MPVLocal].[dbo].[BankAccounts].[NotionalAccount], [MPVLocal].[dbo].[BankAccounts].[TimeStamp] FROM [MPVLocal].[dbo].[BankAccounts] WHERE ( ( [MPVLocal].[dbo].[BankAccounts].[Bank_Acc_ID] = @BankAccId1))',N'@BankAccId1 smallint',@BankAccId1=140 go

Hugh
User
Posts: 13
Joined: 12-Mar-2009
# Posted on: 23-Apr-2009 17:17:40   

When I add a PredicateExpression to the SaveEntity when the record is updated in between fetching and saving it throws the ORMConcurrencyException error and I've tested this numerous times. Happy with thatsimple_smile

However disappointed the first time I tried this concurrency test the line bRet = odap.SaveEntity(obank, True, IP) succeeded even though the record did not update because of the predicateexpressoin on the timestamp which had changed? Maybe I did something stupid but don't thing so.

Hopefully the first result is what happens all the time when concurrency occurs.

Dim IP As IPredicateExpression = New PredicateExpression() IP.Add(BankAccountsFields.TimeStamp = _ obank.Fields("TimeStamp").DbValue) bRet = odap.SaveEntity(obank, True, IP)