我只是想用EF 4.0来实现一些数据库的东西。 我尝试强制使用OptimisticConcurrencyException,但它似乎不起作用。 我假设如果在调用context.SaveChanges()之前数据库上的数据已经发生了变化,那么框架应该抛出一个OC异常 - 但事实并非如此!我查看了update-command和voilà - update命令不包含我在该属性的edmx属性窗口中使用concurrencyMode FIXED标记的实体的属性。
为什么我的数据库表中的更改(将并发模式的某些属性设置为FIXED)没有反映在我的updatecommand中?
以下是我已在某处发布的所有内容,但我想所有问题都会出现,因为我的更新命令中没有反映出FIXED值?
有人知道吗?
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声明:
<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:
<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>
和csdl这个:
<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“历史记录”是使用VS2010中经过修改的ADO.NET POCO实体生成器生成的
这是来源:
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);
}
}
}
我该怎么办?
我有一个通过EF
获取记录的流程A.我有一个进程B通过EF获得相同的记录
在进程A中更改此实体的属性值并运行直到context.SaveChanges()方法(调试器中的断点)
更改进程B中相同属性的值并调用context.SaveChanges()。我也可以直接在数据库中这样做。
糟糕的是,当我跨过进程A中的context.SaveChanges()方法时,没有抛出OC异常,正如我所料,因为数据库中的RowVersion属性存在并且标记为在edmx中修复。
属性更改保存在数据库中。
然后我想到了我的想法 - 但是这个想法并不完全逻辑:为什么我的财产如果不起作用就固定了?
我想我猜为什么不抛出异常。
这是因为固定属性的值不是更新的,EF将比较原始值和此固定属性的modifiedvalue ...且值相同 - &gt;不会引发任何激怒。从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 ==============
有人对我有任何想法吗? 谢谢!
答案 0 :(得分:1)
我在单独的目录中使用cdsl,msdl和ssdl(d:\ webservices,这不是我的程序集输出目录)。 这三个文件我用EDMGEN.exe生成。 线索是,使用EDMGEN.EXE生成的csdl文件与.edmx文件的xml表示形式中的csdl-content-section不同,而edmgen.exe中的csdl文件不包含CONCURRENCYMODE = FIXED属性,而.edmx文件中的csdl内容确实如此。 我不知道如何从我的edmx文件生成3个文件(metadataoutput设置为“copytooutputdirectory” - 但输出目录只包含edmx文件,但我希望这三个文件在那里:-(),但是当我手动修改d:\ webservices中的edmgen.exe的csdl文件时,并发异常行为正常工作!
如果有人可以提出如何在没有edmxgen.exe的情况下重新创建三个文件......我真的很感激: - )