Error OptimisticConcurrencyException: Possible Cause: UpdateCommand

I am just trying to implement database stuff with EF 4.0. I am trying to throw an OptimisticConcurrencyException, but it does not work. I assume that if the data in the database has changed just before I call the context. SaveChanges (), the framework should throw an OS exception, but it is not! I looked at the update-command and voilΓ  command - the update command does not contain properties from the objects that I marked with concurrencyMode FIXED in the edmx properties window for this property.

Why are the changes in my database table (setting some properties as FIXED for concurrency mode) not reflected in my update command?

That is all that I have already posted somewhere, but I think that all problems arise due to FIXED values ​​that are not reflected in my update command?

Anyone got it?

USE [MyProject]
GO

/****** Object:  Table [dbo].[History]    Script Date: 02/19/2011 20:14:49 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[History](
    [HistoryId] [bigint] IDENTITY(1,1) NOT NULL,
    [HistoryKey] [varchar](100) NOT NULL,
    [HistoryText] [varchar](max) NULL,
    [RowVersion] [timestamp] NOT NULL,
 CONSTRAINT [PK_History] PRIMARY KEY CLUSTERED
(
    [HistoryId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO

ssdl states the following:

 <EntityType Name="History">
    <Key>
      <PropertyRef Name="HistoryId" />
    </Key>
    <Property Name="HistoryId" Type="bigint" Nullable="false" StoreGeneratedPattern="Identity" />
    <Property Name="HistoryKey" Type="varchar" Nullable="false" MaxLength="100" />
    <Property Name="HistoryText" Type="xml" />
    <Property Name="RowVersion" Type="timestamp" Nullable="false" StoreGeneratedPattern="Computed" />
  </EntityType>

msl this:

<EntitySetMapping Name="Histories" StoreEntitySet="History" TypeName="MyModel.History">
  <ScalarProperty Name="HistoryId" ColumnName="HistoryId" />
  <ScalarProperty Name="HistoryKey" ColumnName="HistoryKey" />
  <ScalarProperty Name="HistoryText" ColumnName="HistoryText" />
  <ScalarProperty Name="RowVersion" ColumnName="RowVersion" />
</EntitySetMapping>

and csdl this:

<EntityType Name="History">
    <Key>
      <PropertyRef Name="HistoryId" />
    </Key>
    <Property Name="HistoryId" Type="Int64" Nullable="false" annotation:StoreGeneratedPattern="Identity" />
    <Property Name="HistoryKey" Type="String" Nullable="false" MaxLength="100" Unicode="false" FixedLength="false" />
    <Property Name="HistoryText" Type="String" MaxLength="Max" Unicode="true" FixedLength="false" />
    <Property Name="RowVersion" Type="Binary" Nullable="false" MaxLength="8" FixedLength="true" annotation:StoreGeneratedPattern="Computed" />
  </EntityType>

POCO History was created with a modified ADO.NET POCO Entity Generator in VS2010

This is the source:

class Program
{
  static void Main(string[] args)
  {
    using (var context = new MyEntities())
    {
      do
      {
        var query20 = (from p in context.Histories select p).OrderBy(p => p.HistoryId);
        ((ObjectQuery) query20).MergeOption = MergeOption.OverwriteChanges;
        var query2 = query20.ToList();
        History history = query2[0];

        Console.WriteLine("found: " + history.HistoryKey + " ==> " + history.HistoryText + " ==> " +
        Convert.ToBase64String(history.RowVersion));

        var origRowVersion = history.RowVersion;
        Console.WriteLine("Insert new key (q for exit):");
        string newtext = Console.ReadLine();

        if (newtext == "q")
          break;
        history.HistoryText = newtext;

        try
        {
          context.DetectChanges();
          var ose = context.ObjectStateManager.GetObjectStateEntries(EntityState.Modified);
          context.ObjectStateManager.ChangeObjectState(history, EntityState.Modified);
          context.SaveChanges(SaveOptions.DetectChangesBeforeSave);
          var newRowVersion = history.RowVersion;
          if (newRowVersion == origRowVersion)
          {
            Console.WriteLine("rowversion unchanged");
          }
          else
          {
            Console.WriteLine("rowversion changed");
          }
        }
        catch (OptimisticConcurrencyException)
        {
          Console.WriteLine("concurrencyexception occured!");
        }
      } while (true);
    }
  }
}

What should I do?

I have a process A that receives a record through EF

I have process B that gets the same record through EF

Change the property value of this object in process A and run it before using the context.SaveChanges () method (breakpoint in the debugger)

Change the value of the same property in process B and call context.SaveChanges (). I could also do this directly in the database.

, context.SaveChanges() A, OC , , RowVersion , edmx.

.

, , - : , ?

, , .

, , EF ... β†’ . , EF, , ? EF, ( , B ( ))?

- :

=============== BEGIN COMMAND ===============

update [dbo].[History]
set [HistoryText] = @0
where ([HistoryId] = @1)
select [RowVersion]
from [dbo].[History]
where @@ROWCOUNT > 0 and [HistoryId] = @1
@0 = harald
@1 = 1

=============== END COMMAND ===============

? ?

-, :

=============== BEGIN COMMAND ===============

update [dbo].[History]
set [HistoryText] = @0
where ([HistoryId = @1) **AND ([ROWVERSION] = @2))**
select [RowVersion]
from [dbo].[History]
where @@ROWCOUNT > 0 and [HistoryId] = @1
@0 = harald
@1 = 1
**@2 = 0x000000045ef21**

=============== END COMMAND ==============

- ? !

+3
1

, :

cdsl, msdl ssdl (d:\webservices, ). , genereate EDMGEN.exe. , csdl, EDMGEN.EXE, csdl- xml- .edmx, csdl edmgen.exe CONCURRENCYMODE = FIXED, csdl .edmx . , 3 edmx ( metadataoutput "copytooutputdirectory" ), edmx, , :-(), csdl edmgen.exe d:\webservices, concurrency !

- , , edmxgen.exe... : -)

+1

Source: https://habr.com/ru/post/1793307/


All Articles