8

我們使用LINQ to Entities將條目寫入審計數據庫(SQL Server 2008)。由於這是一個專用的審計數據庫,我們只需插入行 - 我們從不讀取任何行,從審計應用程序更新或刪除它們。Entify框架插入需要選擇權限

審計應用程序應該使用最小特權原則,所以我們不希望授予它超出它所需的權限。由於我們從不讀取任何行,因此我們不希望授予從數據庫中進行選擇的權限。

然而,當我們嘗試寫入的數據,我們得到這個錯誤信息:

的SELECT權限是在對象AuditEvent'數據庫「IdentifyAudit」,架構「DBO」拒絕。

的代碼是非常標準的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' 

這就解釋了爲什麼需要 SELECT權限,因爲操作返回的自動生成的ID插入的行。

現在問題仍然存在:我不需要知道剛插入的行的ID,那麼有什麼辦法可以關閉此功能嗎?

+0

SQL事件探查器顯示什麼? – 2009-11-10 08:56:47

+1

編輯問題以包含SQL事件探查器數據。 – 2009-11-10 10:19:57

回答

8

默認情況下,在將實體添加到ObjectContext並調用SaveChanges後,該對象的狀態將從Added添加到Unchanged,並且仍由ObjectContext跟蹤。這就是爲什麼EF需要這個ID,以便它能夠跟蹤它的變化。

Entity Keys and added objects:

1.實體對象被構造。 此時的關鍵屬性的所有 有默認值,null或0

2.新對象添加到 ObjectContext的通過調用 ADDOBJECT或實體的一個 系列特異性的附加方法 上下文或通過調用Add的 導航屬性返回 EntityCollection。

此時,對象服務 生成一個臨時密鑰,它是用於存儲ObjectStateManager中的對象的 。

3.在 ObjectContext上調用SaveChanges。

INSERT語句由 實體服務生成,並在 數據源上執行。

4.如果INSERT操作成功,則將 服務器生成的值寫回 回到ObjectStateEntry。

5. ObjectStateEntry用服務器生成的 值更新 對象。

6.當AcceptChanges的被稱爲上 ObjectStateEntry,永久 的EntityKey正在使用新 服務器生成的值來計算。

所以,就我所知,這是無法切換從ObjectContext的這一特點,我沒有看到任何「好」的解決了這個問題:你能避免這種情況的一種方法是使用自己的存儲過程插入實體(如果可以的話)(http://msdn.microsoft.com/en-us/library/bb399203.aspx)。

而且,如果沒有服務器生成的ID,我認爲,選擇查詢將不會執行(再次,如果你可以改變DBS,如果你想與二代身份證的的打擾)。

3

然而,這是一個老問題,但對於未來也許有人會用。一種方法是僅爲id字段提供選擇權限。