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字段提供选择权限。