Entity Framework 的连接范围





5.00/5 (1投票)
一个允许在单个连接中执行命令的 Entity Framework 的连接范围
引言
这段代码使您能够在业务层中对实体框架数据库操作进行分组,以便即使在后端层中是分离的命令,它们也会在一个单独的打开连接中执行。
背景
如果您使用 TransactionScope
类,那么仍然会有不同的连接(或者至少相同,但会多次打开和关闭),但它们将在分布式事务中运行。我希望例如对于一个导入应用程序,我的导入在一个打开的连接中运行,以解决性能问题。
Using the Code
有两个有趣的类:EntityConnectionScope
和 EntityConnectionScopeHelper
。EntityConnectionScope
是您在业务逻辑中使用的类。在创建时,它会在线程存储中创建一个变量来存储自身。
public EntityConnectionScope()
{
LocalDataStoreSlot slot = Thread.GetNamedDataSlot(Key);
Thread.SetData(slot, this);
}
通过 Current
属性,您可以检索当前作用域。
/// <summary>
/// Gets a reference to the EntityConnectionScope object for the current thread.
/// </summary>
public static EntityConnectionScope Current
{
get
{
EntityConnectionScope scope = null;
LocalDataStoreSlot slot = Thread.GetNamedDataSlot(Key);
scope = Thread.GetData(slot) as EntityConnectionScope;
return scope;
}
}
下一个有趣的部分是 EntityConnection
属性。在第一次调用时,它会初始化一个实体连接并打开它。因为我不知道连接字符串的名称,所以我创建了一个名为 EFConnectionStringName
的新标签在 app.config 文件中,该标签保存连接标签名称。
public EntityConnection EntityConnection
{
get
{
if (entityConnection == null)
{
entityConnection = new EntityConnection
(Configuration.EFConnectionStringName);
}
if (entityConnection.State == ConnectionState.Closed)
{
entityConnection.Open();
}
return entityConnection;
}
}
该类实现了 IDisposable
。如果没有它,就无法使用 using
关键字。它确保在使用 EntityConnectionScope
之后,即使发生异常,连接也会关闭并释放。
public void Dispose()
{
if (entityConnection != null)
{
entityConnection.Close();
entityConnection.Dispose();
}
Thread.FreeNamedDataSlot(Key);
}
助手类在后端使用。在那里,您检查是否激活了 ConnectionScope
。如果是,则获取其连接(已打开)并将其传递给 ObjectContext
。如果不是,则创建一个新连接(不要打开它)并将其传递给 ObjectContext
。
/// <summary>
/// If we are in a ConnectionScope we return that
/// (open) connection, otherwise a new closed one
/// </summary>
/// <returns>EnityConnection</returns>
internal static EntityConnection GetEntityConnection()
{
if (EntityConnectionScope.Current != null)
{
return EntityConnectionScope.Current.EntityConnection;
}
else
{
return new EntityConnection(Configuration.EFConnectionStringName);
}
}
ObjectContext
(这是 EntityFramework
魔术发生的地方)足够聪明,不会在结束时关闭打开的连接。另一方面,如果它收到一个关闭的连接,它会在结束时关闭它。
using (ModelContainer proxy =
new ModelContainer(EntityConnectionScopeHelper.GetEntityConnection()))
{
return proxy.Customers.Include("Orders").SingleOrDefault(c => c.Id == id);
}
EntityScope
的使用非常简单,例如
using (EntityConnectionScope scope = new EntityConnectionScope())
{
//call backend methods here
}
在我的小示例中,我有一个简单的数据模型。Customer : Order = 1 : n。我创建一个客户,然后创建一个订单,最后从后端检索该客户。如您在分析器中看到的那样,它会打开和关闭连接三次(第一个红色矩形)。在 EntityConnectionScope
中执行相同的操作时,连接会为所有三个命令保持打开状态(第二个红色矩形)。

历史
- V 1.0 2010/04/06 初始版本