gpt4 book ai didi

c# - 未抛出 OptimisticConcurrencyException : Possible reason: UpdateCommand

转载 作者:行者123 更新时间:2023-11-30 18:06:00 26 4
gpt4 key购买 nike

我只是想用 EF 4.0 实现一些数据库内容。我尝试强制执行 OptimisticConcurrencyException,但它似乎不起作用。我假设如果数据库中的数据在我调用 context.SaveChanges() 之前发生了变化,框架应该抛出一个 OC 异常——但它没有!我查看了 update-command 和 voilà - update 命令不包含我在该属性的 edmx 属性窗口中用 concurrencyMode FIXED 标记的实体的属性。

为什么我的数据库表中的更改(将某些属性设置为 FIXED 用于并发模式)没有反射(reflect)在我的更新命令中?

这是我已经在某个地方发布的所有内容,但我想所有的问题都是因为我的更新命令中没有反射(reflect)的 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

我有一个通过 EF 获取相同记录的进程 B

在进程A中更改此实体的属性值并运行直到context.SaveChanges()方法(调试器中的断点)

更改进程B中相同属性的值并调用context.SaveChanges()。我也可以直接在数据库中执行此操作。

糟糕的是,当我跨过进程 A 中的 context.SaveChanges() 方法时,没有像我预期的那样抛出 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 ==============

有人对我有什么想法吗?谢谢!

最佳答案

您好,找到了我的问题的答案:

我在单独的目录(d:\webservices,这不是我的程序集输出目录)中使用 cdsl、msdl 和 ssdl。这三个文件是我用 EDMGEN.exe 生成的。线索是,使用 EDMGEN.EXE 生成的 csdl 文件与 .edmx 文件的 xml 表示中的 csdl-content-section 不同,并且来自 edmgen.exe 的 csdl 文件不包含 CONCURRENCYMODE=FIXED 属性,而 .edmx 文件中的 csdl 内容。我不知道如何从我的 edmx 文件中生成这 3 个文件(元数据输出设置为“copytooutputdirectory”——但输出目录只包含 edmx 文件,但我希望这三个文件存在 :-( ),但是当我从 d:\webservices 中的 edmgen.exe 手动修改 csdl 文件时,并发异常行为正常!

如果有人可以建议如何在没有 edmxgen.exe 的情况下重新创建这三个文件...我将非常感激 :-)

关于c# - 未抛出 OptimisticConcurrencyException : Possible reason: UpdateCommand,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5054096/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com