【问题标题】:WCF database connection: only one database connectionWCF数据库连接:只有一个数据库连接
【发布时间】:2015-02-25 10:53:46
【问题描述】:

我需要将 WCF 网络服务连接到 SQL Server 数据库。我只需要使用 SQL 来访问数据,不需要 LINQ 或实体框架。

我尝试按照本教程进行操作: http://www.c-sharpcorner.com/UploadFile/rohatash/inserting-data-into-database-using-wcf-service/ 。 SqlConnection 类好像是我需要用到的,但是当我看到这个服务方法时:

public string InsertUserDetails(UserDetails userInfo)
    {
        // ...
        SqlConnection con = new SqlConnection("Data Source=.;Initial Catalog=Rajesh;User ID=sa;Password=wintellect");
        con.Open();
        SqlCommand cmd = new SqlCommand("insert into RegistrationTable(UserName,Password,Country,Email) values(@UserName,@Password,@Country,@Email)", con);
        cmd.Parameters.AddWithValue("@UserName", userInfo.UserName);
        cmd.Parameters.AddWithValue("@Password", userInfo.Password);
        cmd.Parameters.AddWithValue("@Country", userInfo.Country);
        cmd.Parameters.AddWithValue("@Email", userInfo.Email);
        int result = cmd.ExecuteNonQuery();
        // ...
    }

我很担心,因为显然,每个请求都会创建一个数据库连接。

这是我想要的代码结构示例:

public class Service : IService
{       
    public Company GetCompany(int key)
    {
        // Get existing database connection
        // SELECT * from companies where c_key=key
        // Return Company instance
    }
}

我应该使用什么结构来使用 SQL 访问数据,而不是在每个请求上创建数据库连接?我可以将 SqlConnection 实例设为静态吗?我不明白 WCF 如何处理这个问题,将创建多少个 Service 实例等等。 感谢您的帮助!

【问题讨论】:

  • 你可以创建一个静态:见下面的答案
  • 每次都连接有什么问题?池化处理开销。
  • 我认为理想情况下,只要服务处于活动状态,数据库连接就应该保持打开状态,因为如果 x 个客户端同时连接到 Web 服务,则会创建 x 个数据库连接。我对吗?什么是池化? @DavidP 我想这样做我只是想确保这种方法是正确的!
  • 是的,如果 10 个客户端同时连接到服务,您最终可能会获得 10 个数据库连接——这通常是您想要的,因为您想同时为 10 个客户端提供服务时间。您可以配置 WCF 以将客户端的最大数量限制为您的服务器可以处理的数量——典型的 SQL 服务器可以毫无问题地处理数百到数千个连接;这取决于这些连接在做什么。简单的插入没有问题。如果客户端一一连接,您最终将只有一个与数据库的物理连接(SqlConnection 只是一个包装器)。
  • 实际上,您可能正在为每个客户端会话创建一个全新的服务实例(WCF 服务的默认实例化模式)。我唯一能看出您发布的代码 sn-p 有问题的是 SqlCommandSqlConnection 缺少 using 语句。

标签: c# sql-server wcf


【解决方案1】:

通常最佳做法是仅在需要时保持连接打开。

您可以通过有效管理资源来提高绩效。 ADO.NET 数据提供者对象实现IDisposable,它允许您使用using statements 来确保这些对象及其非托管资源(如数据库连接)得到正确且可预测的释放。

只要您在SqlConnection 对象上调用Dispose()(反过来又调用Close()) - 它就会将连接释放回连接池。

现代 RDBMS 旨在同时处理成千上万个连接。作为开发人员,您的职责是确保仅在需要时保持连接打开。所以打开你的连接,运行你的 SQL,得到你的结果,关闭你的连接。

按照类似的方式:

using (var conn = new SqlConnection(ConnectionString))
{
     conn.Open();
     using (SqlCommand cmd = conn.CreateCommand())
     {
          cmd.CommandText = "SELECT * FROM SomeTable";
          using (SqlDataReader reader = cmd.ExecuteReader())
          {
               while (reader.Read())
               {
                   // DO SOME WORK
               }
          }
     }
}

【讨论】:

  • 非常感谢您的详细解释!这让事情变得非常清楚。
  • 加一个代码片段,我是用手机接的,太乏味了
【解决方案2】:

您的连接代码和命令代码应使用 using 语句来确保正确清理。当您创建初始连接时,池将启动。当连接释放时,它将被释放到池中以再次使用。您可以通过连接字符串控制池的大小。

【讨论】:

    【解决方案3】:

    只要确保每次都打开和关闭它。

    public class Service : IService
    {       
        private static SQLConnection con;
        public Company GetCompany(int key)
        {
            // Get existing database connection
            // SELECT * from companies where c_key=key
            // Return Company instance
        }
    }
    

    【讨论】:

    • 这是个坏主意。通过将实例设为静态,WCF 服务一次只能处理一个请求。更糟糕的是,您实际上需要跟踪关闭连接;在某处出错,下一次调用.Open()(这是无可指责的)将会失败。连接是池化的; SqlConnection 不代表物理连接,到目前为止,处理它们的最明智的方法是尽可能限制它们的范围。
    猜你喜欢
    • 2019-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-07
    • 1970-01-01
    • 2014-03-06
    • 1970-01-01
    相关资源
    最近更新 更多