我们使用LINQ to Entities将条目写入Audit数据库(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事件探查器显示正在执行的语句:
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 :(得分:8)
默认情况下,在向ObjectContext添加实体并调用SaveChanges后,该对象的状态将从Added更改为Unchanged,并且仍由ObjectContext跟踪。这就是EF需要该ID以便能够跟踪其变化的原因。
Entity Keys and added objects:
1.构造实体对象。 此时关键属性全部 有默认值,null或0。
2.新对象被添加到 ObjectContext要么通过调用 AddObject或其中一个实体 特定于集合的添加方法 上下文或通过调用添加 返回一个导航属性 EntityCollection。
此时,对象服务 生成一个临时密钥,即 用于存储对象 ObjectStateManager。
3.SaveChanges被调用 ObjectContext的。
生成INSERT语句 实体服务并在上面执行 数据来源。
4.如果INSERT操作成功, 服务器生成的值被写入 回到ObjectStateEntry。
5. ObjectStateEntry更新 用服务器生成的对象 值。
6.当调用AcceptChanges时 ObjectStateEntry,一个永久物 EntityKey使用new计算 服务器生成的值。
所以,据我所知,不可能从ObjectContext切换这个功能,我没有看到任何“好”的解决方案来解决这个问题:一种避免这种情况的方法是使用你自己的存储过程插入实体(如果可以)(http://msdn.microsoft.com/en-us/library/bb399203.aspx)。
此外,如果没有服务器生成的ID,我认为不会执行选择查询(如果你可以改变dbs,再次,如果你想打扰id的生成)。
答案 1 :(得分:5)
然而,这是一个古老的问题,但未来也许任何人都会使用。一种方法是仅向id字段提供select权限。