Dot-Net

Entify 框架插入需要選擇權限

  • February 13, 2014

我們使用 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。

  1. 通過呼叫 AddObject 或上下文中特定於實體集的添加方法之一或通過在返回 EntityCollection 的導航屬性上呼叫 Add 將新對象添加到 ObjectContext。

此時,Object Services 會生成一個臨時鍵,用於將對象儲存在 ObjectStateManager 中。

3.SaveChanges 在 ObjectContext 上被呼叫。

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

  1. 如果 INSERT 操作成功,伺服器生成的值將被寫回 ObjectStateEntry。

  2. ObjectStateEntry 使用伺服器生成的值更新對象。

6.當在 ObjectStateEntry 上呼叫 AcceptChanges 時,將使用新的伺服器生成的值計算永久 EntityKey。

因此,據我所知,不可能從 ObjectContext 切換此功能,而且我沒有看到任何“好的”解決此問題的方法:避免這種情況的一種方法是使用您自己的儲存過程插入實體(如果可以的話)(http://msdn.microsoft.com/en-us/library/bb399203.aspx)。

此外,如果沒有伺服器生成的 ID,我認為不會執行選擇查詢(同樣,如果您可以更改 dbs,並且如果您想打擾生成 ID)。

引用自:https://stackoverflow.com/questions/1706484