簡體   English   中英

不拋出OptimisticConcurrencyException:可能的原因:UpdateCommand

[英]OptimisticConcurrencyException is not thrown: Possible reason: UpdateCommand

我只是想用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);
    }
  }
}

我該怎么辦?

我有一個進程A通過EF獲取記錄

我有一個進程B通過EF獲得相同的記錄

在進程A中更改此實體的屬性值,並運行到context.SaveChanges()方法(調試器中的斷點)

更改進程B中相同屬性的值並調用context.SaveChanges()。 我也可以直接在數據庫中執行此操作。

不好的是,當我跨過進程A中的context.SaveChanges()方法時,沒有拋出OC異常,正如我所期望的那樣,因為數據庫中的RowVersion屬性存在並且它被標記為固定在EDMX。

屬性更改保存在數據庫中。

那么我認為我得到了一個想法 - 但這個看起來並不完全邏輯:為什么我的財產如果不起作用就固定了?

我想我猜為什么不拋出異常。

這是因為固定屬性的值不是更新的,EF將比較此固定屬性的originalvalue和modifiedvalue ...並且值相同 - >不會拋出excpetion。 從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 ==============

有人對我有任何想法嗎? 謝謝!

嗨,找到了我的問題的答案:

我在一個單獨的目錄中使用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的情況下重新創建三個文件......我真的很感激:-)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM