1

ADO.NET Entity Framework 4 を使用する SQL Server で、"代わりに" トリガーを使用するビューにレコードを挿入すると、無効な操作の例外が発生します。エラー メッセージには次のように表示されます。

{"データベースへの変更は正常にコミットされましたが、オブジェクト コンテキストの更新中にエラーが発生しました。ObjectContext が矛盾した状態にある可能性があります。内部例外メッセージ: EntityKey を定義するキーと値のペアを null または空にすることはできません。パラメータ名前: レコード"}

@ at System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options)
  at System.Data.Objects.ObjectContext.SaveChanges()

この単純化された例では、Contacts と Employers という 2 つのテーブルと、これら 2 つのテーブルに対して行を一度に挿入または取得できる Contacts_x_Employers ビューを 1 つ作成しました。テーブルには Name 属性と ID 属性のみがあり、ビューは両方の結合に基づいています。

CREATE VIEW [dbo].[Contacts_x_Employers]
AS
SELECT dbo.Contacts.ContactName, dbo.Employers.EmployerName
FROM dbo.Contacts INNER JOIN dbo.Employers 
ON dbo.Contacts.EmployerID = dbo.Employers.EmployerID

そして、このトリガーがあります:

Create TRIGGER C_x_E_Inserts
   ON  Contacts_x_Employers
   INSTEAD of INSERT
AS 
BEGIN
    SET NOCOUNT ON;

    insert into Employers (EmployerName)
    select i.EmployerName 
        from inserted i
    where  not i.EmployerName in 
    (select EmployerName from Employers)

    insert into Contacts (ContactName, EmployerID)
    select i.ContactName, e.EmployerID 
    from inserted i inner join employers e
    on i.EmployerName = e.EmployerName;

END
GO

.NET コードは次のとおりです。

using (var Context = new TriggersTestEntities()) { Contacts_x_Employers CE1 = new Contacts_x_Employers(); CE1.ContactName = "J"; CE1.EmployerName = "T"; Contacts_x_Employers CE2 = 新しい Contacts_x_Employers(); CE1.ContactName = "W"; CE1.EmployerName = "C"; Context.Contacts_x_Employers.AddObject(CE1); Context.Contacts_x_Employers.AddObject(CE2); Context.SaveChanges(); // エラーのある行 }

 </p>

SSDL および CSDL (ビュー ノード):

<EntityType Name="Contacts_x_Employers">
   <Key>
    <PropertyRef Name="ContactName" />
<PropertyRef Name="EmployerName" />
   </Key>
<Property Name="ContactName" Type="varchar" Nullable="false" MaxLength="50" />
<Property Name="EmployerName" Type="varchar" Nullable="false" MaxLength="50" />
 </EntityType>

<EntityType Name="Contacts_x_Employers">
  <Key>
     <PropertyRef Name="ContactName" />
     <PropertyRef Name="EmployerName" />
   </Key>
   <Property Name="ContactName" Type="String" Nullable="false" MaxLength="50" Unicode="false" FixedLength="false" />
   <Property Name="EmployerName" Type="String" Nullable="false" MaxLength="50" Unicode="false" FixedLength="false" />
</EntityType>

アプリケーション全体を再作成するための Visual Studio ソリューションと SQL スクリプトは、ftp://JulioSantos.com/files/TriggerBug/ の TestViewTrggers.zip にあります。提供できる支援に感謝します。私はすでにこの問題に何日も費やしました。

4

1 に答える 1

1

「挿入の代わりに」トリガーと「更新の代わりに」トリガーを使用してビューに行を挿入しようとしたときに、同じ問題に遭遇しました。

私は解決策を見つけたと思います.ビジュアルスタジオのウィザードがビューをモデルにドロップすると、一部のプロパティ(おそらくエンティティのキ​​ー)に StoreGeneratedPattern="Identity" が追加されます。

通常のテーブルでリクエストを生成する場合、このプロパティはエンティティ フレームワークに ID が返されることを期待するように指示するため、挿入の最後に select scope_identity() を追加します。

更新可能なビューでは、挿入が別のスコープで発生し、null が返されるため、scope_identity がねじ込まれ、挿入が失敗します。

この StoreGeneratedPattern="Identity" をモデルから削除すると、エンティティ フレームワークは select scope_identity() を追加せず、挿入は正常に機能します。

これで問題が解決し、手遅れにならないことを願っています。

乾杯

詳細はこちら: http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/9fe80b08-0b67-4163-9cb0-41dee5115148/

于 2011-03-08T15:23:04.170 に答える