Entify 框架插入需要選擇權限
我們使用 LINQ to Entities 將條目寫入審計數據庫 (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 Profiler 顯示正在執行的語句:
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,那麼有什麼方法可以關閉此功能嗎?
預設情況下,在將實體添加到 ObjectContext 並呼叫 SaveChanges 後,該對象的狀態會從已添加更改為未更改,並且仍由 ObjectContext 跟踪。這就是 EF 需要該 ID 以便能夠跟踪其更改的原因。
1.構造實體對象。此時鍵屬性都有預設值,要麼為空,要麼為 0。
- 通過呼叫 AddObject 或上下文中特定於實體集的添加方法之一或通過在返回 EntityCollection 的導航屬性上呼叫 Add 將新對象添加到 ObjectContext。
此時,Object Services 會生成一個臨時鍵,用於將對象儲存在 ObjectStateManager 中。
3.SaveChanges 在 ObjectContext 上被呼叫。
INSERT 語句由實體服務生成並在數據源上執行。
如果 INSERT 操作成功,伺服器生成的值將被寫回 ObjectStateEntry。
ObjectStateEntry 使用伺服器生成的值更新對象。
6.當在 ObjectStateEntry 上呼叫 AcceptChanges 時,將使用新的伺服器生成的值計算永久 EntityKey。
因此,據我所知,不可能從 ObjectContext 切換此功能,而且我沒有看到任何“好的”解決此問題的方法:避免這種情況的一種方法是使用您自己的儲存過程插入實體(如果可以的話)(http://msdn.microsoft.com/en-us/library/bb399203.aspx)。
此外,如果沒有伺服器生成的 ID,我認為不會執行選擇查詢(同樣,如果您可以更改 dbs,並且如果您想打擾生成 ID)。