【问题标题】:The Connection is not open while in function using C#使用 C# 运行时连接未打开
【发布时间】:2017-10-07 21:36:06
【问题描述】:

我用于处理 ExecuteScalar Postgresql 查询的方法:

public T ExecuteScalar<T>(string sql, CommandType commandType, List<NpgsqlParameter> parameters)
    {
        using (NpgsqlConnection conn = Konekcija_na_server.Spajanje("spoji")) 
        {
            return Execute<T>(sql, commandType, c =>
            {
                var returnValue = c.ExecuteScalar(); //The Connection is not open.
                return (returnValue != null && returnValue != DBNull.Value && returnValue is T)
                 ? (T)returnValue 
                 : default(T); 
            }, parameters);

        }        
    }

“连接未打开”评论是它发生的地方,我不明白为什么我内部没有连接,所以有人可以解释一下发生了什么吗?

执行方法:

T Execute<T>(string sql, CommandType commandType, Func<NpgsqlCommand, T> function, List<NpgsqlParameter> parameters)
    {
        using (NpgsqlConnection conn = Konekcija_na_server.Spajanje("spoji")) 
            using (var cmd = new NpgsqlCommand())
            {
                cmd.CommandText = sql; 
                cmd.CommandType = commandType; 
                if (parameters.Count > 0 ) 
                {
                    foreach (var parameter in parameters) 
                    {
                        cmd.Parameters.AddWithValue(parameter.ParameterName,parameter.Value); 
                    }
                }
                Konekcija_na_server.Spajanje("prekini");
                return function(cmd); 
            }

        }

    }

我的连接类:

class Konekcija_na_server
{
    public static string Connectionstring = "Server=127.0.0.1;Port=5433;User Id=postgres;" +
    "Password=*********;Database=postgres;Pooling=false;";

    public static NpgsqlConnection Spajanje(string konekcija)
    {
        bool spajanje = false;

        NpgsqlConnection conn = new NpgsqlConnection(Connectionstring);
        if (konekcija == "spoji")
        {             
            conn.Open();
            spajanje = true;
        }
        else if (konekcija == "prekini")
        {
            conn.Close();              
        }

        if (spajanje == true)
        {
            return conn;                
        }
        else return null;

    }

【问题讨论】:

  • @mjwills 什么都没有,因为 c 在那里被声明,所以当你写 conn 时你再次声明它,我们都知道这是一个错误
  • 请包含您的Execute 方法的源代码 - 因为错误在于您的ExecuteExecuteScalar 之间的交互。
  • 您似乎没有将连接分配给命令。您需要在 Execute 方法中替换: using (var cmd = new NpgsqlCommand()) 与 using (var cmd = new NpgsqlCommand(sql, conn)) 并删除 cmd.CommandText = sql;下面一行
  • @IvanMilosavljevic 似乎可行,但你能解释一下原因并给出答案吗?

标签: c# postgresql function executescalar


【解决方案1】:

NpgsqlCommand 缺少连接对象。为了执行查询命令(NpgsqlCommand)需要知道它将执行什么SQL(CommandText),它是什么类型的命令(CommandType = Text,Procedure)和连接。

在下面的行中,您已经创建了命令并分配了文本和命令类型,但您缺少连接。

using (var cmd = new NpgsqlCommand())
cmd.CommandText = sql; 
cmd.CommandType = commandType;  

所以正确的实现应该是:

T Execute<T>(string sql, CommandType commandType, Func<NpgsqlCommand, T> function, List<NpgsqlParameter> parameters)
    {
        using (NpgsqlConnection conn = Konekcija_na_server.Spajanje("spoji")) 
            using (var cmd = new NpgsqlCommand(sql, conn))
            {
                cmd.CommandType = commandType; 
                if (parameters.Count > 0 ) 
                {
                    foreach (var parameter in parameters) 
                    {
                        cmd.Parameters.AddWithValue(parameter.ParameterName,parameter.Value); 
                    }
                }
                Konekcija_na_server.Spajanje("prekini");
                return function(cmd); 
            }

        }

    }

另外,我注意到您正在调用 Konekcija_na_server.Spajanje("prekini"); 来关闭 SQL 连接,但您不是关闭现有连接,而是正在初始化新的 NpgsqlConnection,然后您正在关闭该新连接。 您已经在使用块 using (NpgsqlConnection conn = Konekcija_na_server.Spajanje("spoji")) 内部建立了连接,这意味着当您退出该块时,您的连接将自动关闭

正确的实现是:

public static NpgsqlConnection Spajanje()
{
    var conn = new NpgsqlConnection(Connectionstring);

    conn.Open();
    return conn;

}

【讨论】:

  • 感谢您的回答,我希望有人也会评论该连接类,而您做到了。所以你对我说,通过使用using 语句我关闭连接,甚至不必调用Konekcija_na_server.Spajanje("prekini")。该课程的重点是我有一些其他课程我不使用using 语句,所以我必须以某种方式关闭连接。考虑到这一点,您有任何解决方案如何为这两种情况编辑该类吗?
  • 如果这是大型项目或会随着时间增长的项目,手动关闭连接可能会以失败告终。您可能可以控制当前手动关闭连接的方法,但随着应用程序的增长,它可能会以不良影响结束……已经做到了。简短的回答是您应该在您的案例中使用“工作单元”模式。您可以在codereview.stackexchange.com询问更多详情
  • 再次感谢您的帮助,还有一件事我无法理解。我编辑了我的问题并添加了一个使用 ExecuteScalar 及其返回值的问题。要么我看不清楚发生了什么,要么我为我的问题使用了错误的实现,如果你能看看那个方法及其返回值,将不胜感激 =)
  • 我建议将问题恢复为原始问题并在 stackoverflow 上打开新问题,以便我们可以有一个干净的线程。
  • stackoverflow.com/questions/46629568/… 好了,谢谢你的帮助,我很感激 =)
猜你喜欢
  • 2022-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-21
  • 2019-12-27
  • 2023-04-06
相关资源
最近更新 更多