11

LINQ to Entities を使用して、エントリを Audit データベース (SQL Server 2008) に書き込みます。これは専用の監査データベースであるため、行を挿入するだけで、監査アプリケーションから行を読み取ったり、更新したり、削除したりすることはありません。

監査アプリケーションは最小特権の原則を使用する必要があるため、必要以上のアクセス許可を付与したくありません。行をまったく読み取らないため、データベースから選択する権限を付与したくありません。

ただし、データを書き込もうとすると、次のエラー メッセージが表示されます。

オブジェクト 'AuditEvent'、データベース 'IdentifyAudit'、スキーマ 'dbo' に対する SELECT 権限が拒否されました。

コードは非常に標準的な EF コードです。

var auditEvent = new AuditEvent();
auditEvent.EventType = eventType;
auditEvent.Timestamp = timestamp;
auditEvent.UserName = userName;
auditEvent.ApplicationId = this.ApplicationId;

this.objectContext.AddToAuditEvents(auditEvent);
this.objectContext.SaveChanges();

テーブルへの書き込みに SELECT 権限が必要なのはなぜですか? さらに重要なことに、その要件を削除する方法はありますか?


編集

SQL プロファイラーは、このステートメントが実行されていることを示しています。

exec sp_executesql N'insert [dbo].[AuditEvent]([EventType], [Timestamp], [UserName], [ApplicationId])
values (@0, @1, @2, @3)
select [Id]
from [dbo].[AuditEvent]
where @@ROWCOUNT > 0 and [Id] = scope_identity()',N'@0 nvarchar(10),@1 datetimeoffset(7),@2 nvarchar(11),@3 nvarchar(36)',@0=N'UpdateUser',@1='2009-11-10 10:58:33.2814740 +01:00',@2=N'foo',@3=N'bar'

これは、操作が挿入された行の自動生成された ID を返すため、SELECT 権限が必要な理由を説明しています。

ここで疑問が残ります: 挿入したばかりの行の ID を知る必要はないので、この機能を無効にする方法はありますか?

4

2 に答える 2

9

既定では、エンティティを ObjectContext に追加して SaveChanges を呼び出した後、そのオブジェクトの状態は [追加済み] から [未変更] に変更され、引き続き ObjectContext によって追跡されます。そのため、EF は変更を追跡できるようにその ID を必要とします。

エンティティ キーと追加されたオブジェクト:

1.実体オブジェクトが構築されます。この時点で、主要なプロパティはすべてデフォルト値 (null または 0) になっています。

2. AddObject を呼び出すか、コンテキスト内のエンティティ セット固有の add メソッドの 1 つを呼び出すか、EntityCollection を返すナビゲーション プロパティで Add を呼び出すことによって、新しいオブジェクトが ObjectContext に追加されます。

この時点で、オブジェクト サービスは、オブジェクトを ObjectStateManager に格納するために使用される一時キーを生成します。

3.SaveChanges が ObjectContext で呼び出されます。

INSERT ステートメントは Entity Services によって生成され、データ ソースに対して実行されます。

4.INSERT 操作が成功すると、サーバーによって生成された値が ObjectStateEntry に書き戻されます。

5. ObjectStateEntry は、サーバーが生成した値でオブジェクトを更新します。

6. ObjectStateEntry で AcceptChanges が呼び出されると、新しいサーバー生成値を使用して永続的な EntityKey が計算されます。

したがって、私の知る限り、この機能を ObjectContext から切り替えることはできず、この問題に対する「適切な」解決策は見当たりません。これを回避できる 1 つの方法は、独自のストアド プロシージャを使用してエンティティを挿入することです。 (できれば) ( http://msdn.microsoft.com/en-us/library/bb399203.aspx )。

また、サーバーで生成された ID がない場合、select クエリは実行されないと思います (これも、データベースを変更できる場合、および ID の生成に煩わされたい場合)。

于 2009-11-10T11:44:08.310 に答える
6

ただし、これは古い質問ですが、将来的には誰もが使用する可能性があります。1 つの方法は、id フィールドのみに選択権限を与えることです。

于 2014-02-13T06:14:56.290 に答える