在 asp.net-mvc 网页中关闭 OdbcConnection 的正确模式是什么

发布于 2024-12-17 01:40:01 字数 755 浏览 5 评论 0原文

我有一个网站,并且有一个具有 OdbcConnection 的数据访问类。在构造函数中,我有这样的代码:

    public MySybaseProvider()
    {
        _conn = GetConn();        
    }

    public OdbcConnection GetConn()
    {
        string connString = "DSN=SybaseIQ;Eng=SYSERVER;Links=tcpip(Host=" + _connectionInfo.Host + ";Port=" + _connectionInfo.Port + ");UID=" + _connectionInfo.User + ";PWD=" + _connectionInfo.Pwd + ";";

        return new OdbcConnection(connString);
    }

在整个类中,我有以下代码:

    private OdbcQuery GetQuery(string sql)
    {
        return new OdbcQuery(_conn, sql);
    }

我试图找出确保正确关闭连接的最佳方法。我应该实施 IDisposable 吗?我应该打开和关闭每个查询的连接吗?这里还有其他最佳实践吗?

编辑:

澄清一下,我的用例是我正在加载一个网页,但需要大约 10 个查询才能获取该页面所需的所有数据。

I have a website and I have a data access class that has an OdbcConnection. In the constructor I have this code:

    public MySybaseProvider()
    {
        _conn = GetConn();        
    }

    public OdbcConnection GetConn()
    {
        string connString = "DSN=SybaseIQ;Eng=SYSERVER;Links=tcpip(Host=" + _connectionInfo.Host + ";Port=" + _connectionInfo.Port + ");UID=" + _connectionInfo.User + ";PWD=" + _connectionInfo.Pwd + ";";

        return new OdbcConnection(connString);
    }

and through out the class i have the following code:

    private OdbcQuery GetQuery(string sql)
    {
        return new OdbcQuery(_conn, sql);
    }

I am trying to figure out the best way to make sure I close the connection properly. Should I implement IDisposable? should i open and close the connection on each query? Are there any other best practices here.

EDIT:

To clarify, my use case is that i am loading a single web page but it takes about 10 queries to get all of the data needed for the page.

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

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

发布评论

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

评论(4

2024-12-24 01:40:01

检查ODBC 连接池是否已启用,并创建并打开连接对象对于每次访问数据库都使用 using 语句:(

using (var conn = new OdbcConnection(_connString)) {
  conn.Open();

  // do a database command ...
}

请注意,我更改了设计以将您的 _connString 存储在字段中)

这是最惯用的方式为此,您无需担心在构造函数中创建连接、将其存储在字段中,甚至无需实现 IDisposable

Check if ODBC connection pooling is enabled, and create and open a connection object with the using statement for each of your accesses to the database:

using (var conn = new OdbcConnection(_connString)) {
  conn.Open();

  // do a database command ...
}

(Note that I changed the design to store your _connString in a field)

This is the most idiomatic way to do this, and you don't need to worry about creating your connection in the constructor, storing it in a field, or even implementing IDisposable.

暮年 2024-12-24 01:40:01

所以我提交了另一个答案,因为我意识到我通常使用企业库进行数据访问,而不是纯粹的.net,这会改变一些事情。其中之一是 DataAccessApplicationBlock (DAAB) 负责打开和关闭到数据库的连接,所以我没有太多,因此我像下面一样使用它。此外,在这种情况下,执行所描述的操作的一种更简单、更有效的方法是执行 1 个存储过程中的所有 SELECT 语句,然后一次读取并解析每个结果集。

示例:

存储过程

Create PROCEDURE [dbo].[GetUserByEmail]
    @UserID int,
    @AccountID int,
AS
BEGIN
    SET NOCOUNT OFF;

    SELECT * FROM Users WHERE UserID = @UserID and AccountID = @AccountID

    SELECT * FROM UserAddresses WHERE UserID = @UserID
END

C# 代码:

public class DataAccessLayer
{
    private static DataAccessLayer me = new DataAccessLayer();

    private DataAccessLayer() { }

    public static DataAccessLayer GetInstance()
    {
        return me;
    }

    public Database GetDatabase(string connectionString, string provider)
    {
       DbProviderFactory providerFactory = DbProviderFactories.GetFactory(provider);

        return new GenericDatabase(connectionString,
                                   providerFactory);
    }
}

public class Repository
{
    protected Database curDatabase;

    public Repository()
    {
        curDatabase = DataAccessLayer.GetInstance().GetDatabase("ConnectionString", "System.Data.Odbc");
    }

    public Database CurrentDatabase
    {
        get { return curDatabase; }
    }
}

public class UserRepository : Repository
{
    public User GetUser(int urserID, int accountID)
    {
        using (IDataReader dataReader = CurrentDatabase.ExecuteReader("StroedProcName", urserID, accountID))
        {
            //User Details
            while (dataReader.Read())
            {
                //Parse Data
            }

            dataReader.NextResult();

            //User Address(es)
            while (dataReader.Read())
            {
                //Parse Data
            }
        }
    }
}

So I have submitted another Answer Because I realised that I usually use Enterprise Library for my Data Access and not pure .net which changes things a bit. For one the DataAccessApplicationBlock (DAAB) takes care of opening and closing the Connection(s) to the Database so I don't have too, therefore I use it like below. Also in this case a easier and more effiecint way to do what is described is to execute all the SELECT Statements in 1 Stored Proc and Then Read through and Parse each result set one at a time.

Example:

Stored Proc

Create PROCEDURE [dbo].[GetUserByEmail]
    @UserID int,
    @AccountID int,
AS
BEGIN
    SET NOCOUNT OFF;

    SELECT * FROM Users WHERE UserID = @UserID and AccountID = @AccountID

    SELECT * FROM UserAddresses WHERE UserID = @UserID
END

C# Code:

public class DataAccessLayer
{
    private static DataAccessLayer me = new DataAccessLayer();

    private DataAccessLayer() { }

    public static DataAccessLayer GetInstance()
    {
        return me;
    }

    public Database GetDatabase(string connectionString, string provider)
    {
       DbProviderFactory providerFactory = DbProviderFactories.GetFactory(provider);

        return new GenericDatabase(connectionString,
                                   providerFactory);
    }
}

public class Repository
{
    protected Database curDatabase;

    public Repository()
    {
        curDatabase = DataAccessLayer.GetInstance().GetDatabase("ConnectionString", "System.Data.Odbc");
    }

    public Database CurrentDatabase
    {
        get { return curDatabase; }
    }
}

public class UserRepository : Repository
{
    public User GetUser(int urserID, int accountID)
    {
        using (IDataReader dataReader = CurrentDatabase.ExecuteReader("StroedProcName", urserID, accountID))
        {
            //User Details
            while (dataReader.Read())
            {
                //Parse Data
            }

            dataReader.NextResult();

            //User Address(es)
            while (dataReader.Read())
            {
                //Parse Data
            }
        }
    }
}
诗化ㄋ丶相逢 2024-12-24 01:40:01

我认为你绝对应该实现 IDisposable 并遵循 处置模式 请记住,垃圾收集器对 IDisposable 一无所知。作为最后的手段,您应该有一个终结器,它会在需要时终止数据库连接,但尽可能抑制终结器(请参阅我添加的链接以了解所有血淋淋的详细信息)。

至于您是想为每个命令创建一个新连接还是在对象的整个生命周期中保留一个连接,这更加主观,并且取决于您的场景、环境和许多其他因素。我建议探索两者并看看你的想法。如果这是一个“真正的”数据库,也许可以与 DBA 交谈并看看他们的想法。

无论哪种方式,实现 IDisposable 都是您的朋友,因为您可以以所有 .NET 开发人员都熟悉的模式拥有漂亮、干净、定义良好的处理代码。

I would argue you definitely should implement IDisposable and follow the dispose pattern Keep in mind the garbage collector knows nothing about IDisposable. You should as a last resort have a finalizer that will kill the DB connection if need be, but suppress the finalizer whenever possible (see the link I added for all the gory details).

As to whether you want to create a new connection per command or keep one around for the life of the object, that's much more subjective and depends on your scenario, environment, and many other things. I recommend exploring both and see what you think. If this is a "real" DB, perhaps talk to the DBA and see what they think.

Either way, implementing IDisposable is your friend, as you can have nice, clean, well defined disposing code in a pattern that all .NET developers are familiar with.

明天过后 2024-12-24 01:40:01

您可以使用以下模式来确保连接已释放。即使发生错误,也会被处理掉。为了更安全的编码,您应该使用连接字符串生成器来构建连接。您应该仅在计划执行操作时创建/使用连接。它不应该在您的应用程序的整个生命周期中徘徊。您可以使用连接字符串/属性来代替。

    public OdbcConnection GetConn()
    {
        OdbcConnectionStringBuilder sb = new OdbcConnectionStringBuilder();
        sb.Driver = "Microsoft Access Driver (*.mdb)";
        sb.Add("Dbq", "C:\\info.mdb");
        sb.Add("Uid", "Admin");
        sb.Add("Pwd", "pass!word1");
        OdbcConnection con = new OdbcConnection(sb.ConnectionString);
        return con;
    }


    public void DoSomeWork()
    {
        using(OdbcConnection connection = GetConn())
        {
            // Do stuff with your connection here


        }
    }

You can use the following pattern to ensure the connection is disposed. Even if an error occurs it will be disposed of. For safer coding you should use a connection string builder to build the connection. You should only create / use the connection when you are planning to perform an operation. It should NOT hang around for the life of your application. You can use the connection string / properties for that instead.

    public OdbcConnection GetConn()
    {
        OdbcConnectionStringBuilder sb = new OdbcConnectionStringBuilder();
        sb.Driver = "Microsoft Access Driver (*.mdb)";
        sb.Add("Dbq", "C:\\info.mdb");
        sb.Add("Uid", "Admin");
        sb.Add("Pwd", "pass!word1");
        OdbcConnection con = new OdbcConnection(sb.ConnectionString);
        return con;
    }


    public void DoSomeWork()
    {
        using(OdbcConnection connection = GetConn())
        {
            // Do stuff with your connection here


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