多用户同时连接并执行 CRUD

发布于 2024-11-05 21:09:58 字数 1525 浏览 0 评论 0原文

我正在使用 ASP.NET Framework 4、IIS 7 和 SQL Server 2008 R2。

我有一个错误,例如: 在选定的数据源中找不到{column}, SQL Reader 已关闭,...

仅在以下情况下发生:

  1. 多个用户已连接。
  2. 他们同时进行 CRUD(创建、检索、更新、删除)调用。

奇怪的是,它逃脱了我的捕获:

try{
    Connexion_D.GetConnected();
    // doing CRUD
}
catch{
    // catching Error, avoid yellow page aspx
}
finally
{
    Connexion_D.CloseConnection();
} 

和我的连接类:

public class Connexion_D
{

    static public SqlConnection conn;
    static public SqlConnection GetConnected()
    {
        try
        {
            String strConnectionString = ConfigurationManager.ConnectionStrings["xxxxx"].ConnectionString;
            conn = new SqlConnection(strConnectionString);
        }
        catch (Exception excThrown)
        {
            conn = null;
            throw new Exception(excThrown.InnerException.Message, excThrown);
        }

        // Ouverture et restitution de la connexion en cours
        if (conn.State == ConnectionState.Closed) conn.Open();
        return conn;
    }
    static public Boolean IsConnected
    {
        get { return (conn != null) && (conn.State != ConnectionState.Closed) && (conn.State != ConnectionState.Broken); }
    }

    static public void CloseConnection()
    {
        // Libération de la connexion si elle existe
        if (IsConnected) conn.Close();
    }
}

所以我不认为代码是错误的/有错误。

我认为可能是IIS和SQL Server的配置问题。

有什么想法吗?

提前致谢。

I'm using ASP.NET Framework 4, IIS 7 and SQL Server 2008 R2.

I have got an error like:
{column} not found in selected DataSource,
SQL Reader is close
, ....

It only happens when:

  1. Multiple users are connected.
  2. They make CRUD (Create, Retrive, Update, Delete) calls simultaneously.

Strangely, it escape my catch:

try{
    Connexion_D.GetConnected();
    // doing CRUD
}
catch{
    // catching Error, avoid yellow page aspx
}
finally
{
    Connexion_D.CloseConnection();
} 

And my connection class:

public class Connexion_D
{

    static public SqlConnection conn;
    static public SqlConnection GetConnected()
    {
        try
        {
            String strConnectionString = ConfigurationManager.ConnectionStrings["xxxxx"].ConnectionString;
            conn = new SqlConnection(strConnectionString);
        }
        catch (Exception excThrown)
        {
            conn = null;
            throw new Exception(excThrown.InnerException.Message, excThrown);
        }

        // Ouverture et restitution de la connexion en cours
        if (conn.State == ConnectionState.Closed) conn.Open();
        return conn;
    }
    static public Boolean IsConnected
    {
        get { return (conn != null) && (conn.State != ConnectionState.Closed) && (conn.State != ConnectionState.Broken); }
    }

    static public void CloseConnection()
    {
        // Libération de la connexion si elle existe
        if (IsConnected) conn.Close();
    }
}

So I don't think the code is wrong / has a bug.

I think it may be the configuration of IIS and SQL server.

Any ideas?

Thanx in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

薄荷港 2024-11-12 21:09:58

如果我理解你在做什么,那么这看起来非常可疑:

static public SqlConnection conn;     
static public SqlConnection GetConnected() {         
    try         
    {             
        String strConnectionString = ConfigurationManager.ConnectionStrings["xxxxx"].ConnectionString;             
        conn = new SqlConnection(strConnectionString);
    } 
}

static public void CloseConnection() {           
    // Libération de la connexion si elle existe           
    if (IsConnected) conn.Close();       
}   

你正在使用静态连接变量,这意味着当你关闭它时,你正在关闭最后一个打开的连接变量。

在多用户场景中,您可能会遇到这种情况:

  • 用户 A:创建连接(并返回连接 1)
  • 用户 A:执行查询(针对连接 1 运行)
  • 用户 B:创建连接(并返回连接 2)
  • 用户 A:关闭连接(最后一个打开的是 2,因此已关闭)
  • 用户 B:执行查询(针对连接 2 运行,它已被关闭...砰)

另外,您可能应该重新考虑将连接作为公共成员变量:

static public SqlConnection conn;     

这通常被认为是不好的做法,如果类之外的任何代码开始扰乱其内部变量,则可能会在将来导致意外/难以追踪的错误。

编辑:

最明显的解决方案似乎是阻止静态连接。您的客户端代码可能如下所示:

try{
    // use using block around connection, calls dispose automatically when
    // block ends...
    using(var connectionWrapper = new Connexion_D()) {
        var connectedConnection = connectionWrapper.GetConnected();        
        // do CRUD
    }
}
catch{
    // catching Error, avoid yellow page aspx
    // Really you should probably be doing something with the exception (logging?)
    // particularly since you go to the effort of throwing it from your Connection_D
    // class.
}

您的类代码如下所示:

/* Implement IDisposable to cleanup connection */
public class Connexion_D : IDisposable 
{
    public SqlConnection conn;

    public SqlConnection GetConnected()
    {
        try
        {
            String strConnectionString = ConfigurationManager.ConnectionStrings["xxxxx"].ConnectionString;
            conn = new SqlConnection(strConnectionString);
        }
        catch (Exception excThrown)
        {
            conn = null;
            throw new Exception(excThrown.InnerException.Message, excThrown);
        }

        // Ouverture et restitution de la connexion en cours
        if (conn.State == ConnectionState.Closed) conn.Open();
        return conn;
    }
    public Boolean IsConnected
    {
        get { return (conn != null) && (conn.State != ConnectionState.Closed) && (conn.State != ConnectionState.Broken); }
    }

    public void CloseConnection()
    {
        // Libération de la connexion si elle existe
        if (IsConnected) { 
            conn.Close();
            conn = null;
        }
    }

    // Implement IDisposable.
    // Do not make this method virtual.
    // A derived class should not be able to override this method.
    public void Dispose()
    {
        // Close connection
    }
}

请参阅 this 了解有关实现 IDisposable 的更多信息。

If I understand what you're doing correctly, then this looks very dubious:

static public SqlConnection conn;     
static public SqlConnection GetConnected() {         
    try         
    {             
        String strConnectionString = ConfigurationManager.ConnectionStrings["xxxxx"].ConnectionString;             
        conn = new SqlConnection(strConnectionString);
    } 
}

static public void CloseConnection() {           
    // Libération de la connexion si elle existe           
    if (IsConnected) conn.Close();       
}   

You're working with a static connection variable, which means that when you close it, you're closing the last one that was opened.

In a multi-user scenario, you could be having this happen:

  • User A: Create connection (and return connection 1)
  • User A: Execute query (runs against connection 1)
  • User B: Create connection (and return connection 2)
  • User A: Close connection (last one opened was 2, so that's closed)
  • User B: Execute query (runs against connection 2, it's already been closed... bang)

As an aside, you should probably reconsider having your connection as a public member variable:

static public SqlConnection conn;     

This is generally considered bad practice and can lead to unexpected / hard to track down errors in the future if any code outside of your class starts messing about with it's internal variables.

EDIT:

The most obvious solution would seem to be to stop the connection from being static. You client code might then look something like this:

try{
    // use using block around connection, calls dispose automatically when
    // block ends...
    using(var connectionWrapper = new Connexion_D()) {
        var connectedConnection = connectionWrapper.GetConnected();        
        // do CRUD
    }
}
catch{
    // catching Error, avoid yellow page aspx
    // Really you should probably be doing something with the exception (logging?)
    // particularly since you go to the effort of throwing it from your Connection_D
    // class.
}

With your class code looking like:

/* Implement IDisposable to cleanup connection */
public class Connexion_D : IDisposable 
{
    public SqlConnection conn;

    public SqlConnection GetConnected()
    {
        try
        {
            String strConnectionString = ConfigurationManager.ConnectionStrings["xxxxx"].ConnectionString;
            conn = new SqlConnection(strConnectionString);
        }
        catch (Exception excThrown)
        {
            conn = null;
            throw new Exception(excThrown.InnerException.Message, excThrown);
        }

        // Ouverture et restitution de la connexion en cours
        if (conn.State == ConnectionState.Closed) conn.Open();
        return conn;
    }
    public Boolean IsConnected
    {
        get { return (conn != null) && (conn.State != ConnectionState.Closed) && (conn.State != ConnectionState.Broken); }
    }

    public void CloseConnection()
    {
        // Libération de la connexion si elle existe
        if (IsConnected) { 
            conn.Close();
            conn = null;
        }
    }

    // Implement IDisposable.
    // Do not make this method virtual.
    // A derived class should not be able to override this method.
    public void Dispose()
    {
        // Close connection
    }
}

See this for more information about implementing IDisposable.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文