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
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 ==============
- ?
!