gpt4 book ai didi

sql-server - 使用 SqlConnection/System.Transactions 的每个请求 session

转载 作者:行者123 更新时间:2023-12-02 07:10:43 25 4
gpt4 key购买 nike

我刚刚开始在一个项目中使用 Dapper,过去几年主要使用 NHibernate 和 EF 等 ORM。

通常在我们的网络应用程序中,我们为每个请求实现 session ,在请求开始时开始一个事务并在结束时提交它。

直接使用 SqlConnection/System.Transactions 时我们是否应该做类似的事情?

StackOverflow 是如何做到的?

解决方案

听取@gbn 和@Sam Safron 的建议,我没有使用事务。就我而言,我只执行读取查询,因此似乎没有真正要求使用事务(与我被告知的隐式事务相反)。

我创建了一个轻量级 session 接口(interface),以便我可以为每个请求使用一个连接。这对我来说非常有益,因为使用 Dapper 时,我经常需要创建一些不同的查询来构建一个对象,并且宁愿共享相同的连接。

确定每个请求的连接范围并对其进行处置的工作是由我的 IoC 容器(StructureMap)完成的:

public interface ISession : IDisposable {
IDbConnection Connection { get; }
}

public class DbSession : ISession {

private static readonly object @lock = new object();
private readonly ILogger logger;
private readonly string connectionString;
private IDbConnection cn;

public DbSession(string connectionString, ILogger logger) {
this.connectionString = connectionString;
this.logger = logger;
}

public IDbConnection Connection { get { return GetConnection(); } }

private IDbConnection GetConnection() {
if (cn == null) {
lock (@lock) {
if (cn == null) {
logger.Debug("Creating Connection");
cn = new SqlConnection(connectionString);
cn.Open();
logger.Debug("Opened Connection");
}
}
}

return cn;
}

public void Dispose() {
if (cn != null) {
logger.Debug("Disposing connection (current state '{0}')", cn.State);
cn.Dispose();
}
}
}

最佳答案

这就是我们所做的:

我们在名为 Current 的对象上定义一个名为 DB 的静态变量

public static DBContext DB
{
var result = GetContextItem<T>(itemKey);

if (result == null)
{
result = InstantiateDB();
SetContextItem(itemKey, result);
}

return result;
}

public static T GetContextItem<T>(string itemKey, bool strict = true)
{

#if DEBUG // HttpContext is null for unit test calls, which are only done in DEBUG
if (Context == null)
{
var result = CallContext.GetData(itemKey);
return result != null ? (T)result : default(T);
}
else
{
#endif
var ctx = HttpContext.Current;
if (ctx == null)
{
if (strict) throw new InvalidOperationException("GetContextItem without a context");
return default(T);
}
else
{
var result = ctx.Items[itemKey];
return result != null ? (T)result : default(T);
}
#if DEBUG
}
#endif
}

public static void SetContextItem(string itemKey, object item)
{
#if DEBUG // HttpContext is null for unit test calls, which are only done in DEBUG
if (Context == null)
{
CallContext.SetData(itemKey, item);
}
else
{
#endif
HttpContext.Current.Items[itemKey] = item;

#if DEBUG
}
#endif
}

在我们的例子中,InstantiateDB 返回一个 L2S 上下文,但在您的例子中,它可能是一个开放的 SQLConnection 或其他内容。

在我们的应用程序对象上,我们确保连接在请求结束时关闭。

   protected void Application_EndRequest(object sender, EventArgs e)
{
Current.DisposeDB(); // closes connection, clears context
}

然后,在代码中需要访问数据库的任何位置,您只需调用 Current.DB 即可自动工作。由于所有 #if DEBUG 内容,这也是单元测试友好的。

<小时/>

我们不会在每个 session 中启动任何事务,如果我们这样做并在 session 开始时进行更新,我们将遇到严重的锁定问题,因为锁直到结束才会被释放。

关于sql-server - 使用 SqlConnection/System.Transactions 的每个请求 session ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6201874/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com