2011-11-17 58 views
3

我需要在sql server上使用应用程序规则安全性。我想使用Enity Framework Code First。带SQL服务器应用程序角色的EF

成功登录后,我的连接被设置为应用程序角色。然后我使用这个连接创建我的DbContext。

但是:EF期望一个封闭的连接对象。关闭连接会降低应用程序角色。

我该如何解决这个困境?

回答

6

我设法得到这个工作有两个步骤:

交换机连接池关闭,这是提到的所有时间使用应用程序角色的连接。由于我有桌面应用程序,这对我来说不成问题。

添加一个处理程序到DbConnection.StateChanged并在连接的每个打开时激活应用程序角色。没有连接池,关闭时不需要sp_unsetapprole。因此,这对我的作品:

context.Database.Connection.StateChanged += (sender, args) => 
    if (args.CurrentState == ConnectionState.Open) { 
    activateAppRole((DbConnection)sender, ...); 
    } 
} 

我想,如果池是非常重要的人,她可以叫sp_unsetapprole在关闭这个相同的处理程序的连接。

0

EF对此没有任何本机支持。我想解决方法可以是:

  • 创建您自己的连接并将它传递(关闭)到EF上下文/ EntityConnection。这应该强制您将在您的控制下有连接生命周期,并且EF不会关闭它(但我已经看到抱怨说它不适用于DbContext)。
  • 一旦您创建了上下文创建的设置应用程序角色的实例。上下文本身不应该对数据库产生任何查询(除了代码首先检查数据库版本的DbContext除外),所以在创建上下文后设置角色不应引起任何问题。
+0

不幸的是,DbContext总是打开和关闭连接,所以你的猜测不起作用。 – okrumnow

4

由于这个问题在搜索结果列表中很高,我只想提出一个谨慎的话。我有一个应用程序需要使用应用程序角色,并且okrumnow的解决方案似乎首先起作用。

然而,在单元测试我发现,有时候处理StateChanged事件将导致两次上调的情况下,你会得到错误:

"Impersonate Session Security Context" cannot be called in this batch because a simultaneous batch has called it.

这似乎有助于条件更改为:

args.CurrentState == ConnectionState.Open && 
    args.CurrentState == ConnectionState.Closed 

但它仍然不能消除错误。我在EF4.3和EF5中证实了这一点。 Ladislav正确的是,理想的方式是为DbContext创建一个连接并告诉上下文它不拥有它。

此外,由于没有ConnectionState.Closing事件,因此在连接关闭之前可以拨打sp_unsetapprole,因此连接池永远不可能使用此设置。

由于我具有灵活性,我的解决方案是消除应用程序角色的使用并使用专用的SQL登录。无论哪种方式,你是硬编码的密码...

相关问题