65.9K
CodeProject 正在变化。 阅读更多。
Home

Entity Framework 的连接范围

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2010年4月6日

CPOL

2分钟阅读

viewsIcon

49186

downloadIcon

514

一个允许在单个连接中执行命令的 Entity Framework 的连接范围

注意:这段代码适用于 VS 2010 和 EF v4。

引言

这段代码使您能够在业务层中对实体框架数据库操作进行分组,以便即使在后端层中是分离的命令,它们也会在一个单独的打开连接中执行。 

背景

如果您使用 TransactionScope 类,那么仍然会有不同的连接(或者至少相同,但会多次打开和关闭),但它们将在分布式事务中运行。我希望例如对于一个导入应用程序,我的导入在一个打开的连接中运行,以解决性能问题。

Using the Code

有两个有趣的类:EntityConnectionScope EntityConnectionScopeHelperEntityConnectionScope 是您在业务逻辑中使用的类。在创建时,它会在线程存储中创建一个变量来存储自身。

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 初始版本 
实体框架的连接作用域 - CodeProject - 代码之家
© . All rights reserved.