1

我们希望在 IIS 中有一个托管的 C# Web 服务,我可以将它传递给它的方法 SOL Query,然后它对存在于同一服务器中的 Access 2007 DB 文件执行查询,该文件包含 Web 服务并返回数据。

我们已经使用了以下代码

<%@ WebService Language="C#" 
  CodeBehind="~/App_Code/Service.cs" 
  Class="Service" %>
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;

using System.Data;
using System.Data.OleDb;
using System.IO;

public class Service : System.Web.Services.WebService
{
    [WebMethod]
    public DataSet ExecuteQuery(string sqlQuery) 
    {
        OleDbConnection conn = new OleDbConnection(
             @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + 
             @"C:\Folder\Database2.accdb;Persist Security Info=False;");

        OleDbDataAdapter da = new OleDbDataAdapter(sqlQuery, conn);
        DataSet ds = new DataSet();
        da.Fill(ds);            
        return ds;
    }

}

但是当我们调用这个方法时,页面只是显示为加载(正在进行),但没有任何数据返回或异常。

4

2 回答 2

6

我可以建议对您的设计和代码结构进行一些改进吗?

1.重新评估将其设为 Web 服务的原因。你能把它编译成一个类库程序集(.dll)并从其他项目中引用它吗?进行 Web 服务调用的开销或时间成本远大于对另一个库的引用。是的,您必须处理 Access 的配置问题。

2.重新考虑您希望每次调用都返回 DataSet 的原因。这是一篇关于 ADO.NET 数据集缺点的优秀文章:www.4guysfromrolla.com/articles/050405-1.aspx

3.在没有先评估或参数化它的情况下,不要执行给你的任何字符串。我理解创建一个层来为你处理所有数据库查询的愿望,你应该为这个想法喝彩。但是,所呈现的代码会造成更危险的情况,因为它不会检查任何格式错误的语句等。因此建议不要执行传递给您的任何字符串。也许这个网络服务只在你的局域网内,也许你相信所有的调用都是诚实的和非破坏性的。我们可能认为所有的内部活动都是好的,但一旦员工变坏,你就为内部破坏打开了可能性。

当有人像这样调用您的网络服务时会发生什么:

ExecuteQuery("DELETE FROM Customers")

或者

ExecuteQuery("UPDATE Employee SET Salary = 250000 WHERE ID= 9")

或者

ExecuteQuery("SELECT Salary WHERE EmployeePosition = 'CEO'")

4.为您希望图层公开的每个功能创建一个新的 Web 方法。例如,代替客户端调用

ExecuteQuery("SELECT ID, CustomerName FROM Customers ORDER BY CustomerName")

做这个:

public List<Customer> ListAllCustomers()

考虑创建这样的方法:

public void UpdateEmployee(Employee emp)

或者

public void UpdateEmployeeSalary(string id, double salary) 

5.将您的 Access 连接字符串放入app.config文件中。参考System.Configuration和使用ConfigurationManager。每次调用查询时加载它。这有点影响性能,但在更改 .mdb 文件的目录路径或名称时,维护工作量实际上为零。

  private string GetConnectionString()
        {
           //do some more checking on whether the value exists as well, instead of just returning it!
            return ConfigurationManager.AppSettings["MyAccessDB"].ToString();
        }
于 2009-06-01T17:11:22.783 回答
0

还:

using (OleDbConnection conn = new OleDbConnection(
         @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + 
         @"C:\Folder\Database2.accdb;Persist Security Info=False;"))
{
    using (OleDbDataAdapter da = new OleDbDataAdapter(sqlQuery, conn))
    {
        DataSet ds = new DataSet();
        da.Fill(ds);            
        return ds;
    }
}

除非您喜欢资源泄漏,否则请执行此操作。

于 2009-06-01T17:15:23.170 回答