11

我们使用 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,那么有什么方法可以关闭此功能吗?

4

2 回答 2

9

默认情况下,在将实体添加到 ObjectContext 并调用 SaveChanges 后,该对象的状态会从已添加更改为未更改,并且仍由 ObjectContext 跟踪。这就是 EF 需要该 ID 以便能够跟踪其更改的原因。

实体键和添加的对象:

1.构造实体对象。此时键属性都有默认值,要么为空,要么为 0。

2. 通过调用 AddObject 或上下文中特定于实体集的添加方法之一或通过在返回 EntityCollection 的导航属性上调用 Add 将新对象添加到 ObjectContext。

此时,Object Services 会生成一个临时键,用于将对象存储在 ObjectStateManager 中。

3.SaveChanges 在 ObjectContext 上被调用。

INSERT 语句由实体服务生成并在数据源上执行。

4. 如果 INSERT 操作成功,服务器生成的值将被写回 ObjectStateEntry。

5. ObjectStateEntry 使用服务器生成的值更新对象。

6.当在 ObjectStateEntry 上调用 AcceptChanges 时,将使用新的服务器生成的值计算永久 EntityKey。

因此,据我所知,无法从 ObjectContext 切换此功能,而且我没有看到任何“好的”解决此问题的方法:避免这种情况的一种方法是使用您自己的存储过程插入实体(如果可以的话)(http://msdn.microsoft.com/en-us/library/bb399203.aspx)。

此外,如果没有服务器生成的 ID,我认为将不会执行选择查询(同样,如果您可以更改 dbs,并且如果您想打扰 id 的生成)。

于 2009-11-10T11:44:08.310 回答
6

但是,这是一个老问题,但将来也许有人会使用。一种方法是仅将选择权限授予 id 字段。

于 2014-02-13T06:14:56.290 回答