【问题标题】:How pass dataset to WCF method as a parameter如何将数据集作为参数传递给 WCF 方法
【发布时间】:2017-04-10 17:15:20
【问题描述】:

在那里,我使用此代码读取 excel 文件的数据,它对我来说可以正常工作。但我需要使用WCF 将此数据集保存到数据库中。所以认为将dataset 传递给 wcf 方法来实现这一点。但是我该怎么做呢

这是我用 Windows 窗体应用程序尝试的代码

 private void button1_Click(object sender, EventArgs e)
   {
       OpenFileDialog opn = new OpenFileDialog();
       opn.Filter = "Excel Files|*.xls;*.xlsx;*.xlsm";

        if (opn.ShowDialog() == DialogResult.Cancel)
            return;

            FileStream strm = new FileStream(opn.FileName, FileMode.Open);
            IExcelDataReader excldr = ExcelReaderFactory.CreateOpenXmlReader(strm);

            DataSet rslt = excldr.AsDataSet();

           // while (excldr.Read())
           // {
           //    Console.WriteLine(excldr.GetString(1));
           // }
  }

我需要将DataSet rslt 传递给WCF 方法,并且在WCF 内我想编写保存数据功能。这是一种好习惯吗?那么我该怎么做呢

【问题讨论】:

标签: c# wcf dataset


【解决方案1】:

通过 WCF 传递 DataTable 或 DataSet 是一个备受争议的话题。 它可以很容易地完成,但是我个人更喜欢传递数据本身而不是元​​数据(列和行定义、数据关系等) 我通常声明一个对象,将它暴露给 WCF 并传输它。

对于 DataSet 中的每个表,您可以执行以下操作(未测试):

 public class ExcelService : IExcelService
{
    public List<CustomExcelData> GetExcelData()
    {
        List<CustomExcelData> excelDataList = new List<CustomExcelData>();
        OpenFileDialog opn = new OpenFileDialog();
        opn.Filter = "Excel Files|*.xls;*.xlsx;*.xlsm";

        if (opn.ShowDialog() == DialogResult.Cancel)
            return null;

        FileStream strm = new FileStream(opn.FileName, FileMode.Open);
        IExcelDataReader excldr = ExcelReaderFactory.CreateOpenXmlReader(strm);

        DataSet rslt = excldr.AsDataSet();

        DataTable dt = rslt.Tables[0];

        if (dt != null && dt.Rows.Count > 0)
        {
            foreach (DataRow row in dt.Rows)
            {
                excelDataList.Add(new CustomExcelData(row));
            }
        }

        return excelDataList;
    }
}

和界面:

[ServiceContract]
interface IExcelService
{
    [OperationContract]
    List<CustomExcelData> GetExcelData();
}

[DataContract]
public class CustomExcelData
{
    [DataMember]
    public string Name { get; set; }
    [DataMember]
    public string Address { get; set; }
    [DataMember]
    public DateTime BirthDate { get; set; }

    public CustomExcelData(DataRow row)
    {
        Name = row["NameField"].ToString();
        Address = row["AddressField"].ToString();
        BirthDate = DateTime.Parse(row["BirthDateField"].ToString());
    }

}

【讨论】:

    【解决方案2】:

    在阅读了您的评论后,我想我应该给您一些示例,如何以稍微更好的方式解决这个问题。

    我的方法是初始化 Request/Response DataContract 对象,允许客户端发送数据集并更有效地接收确认。

    这是DataContract 类:

    客户端将实例化并填充并发送到服务的请求对象:

    [DataContract]
    public class SaveDataSetRequest
    {
        [DataMember]
        public DataSet Data { get; set; }
    
        [DataMember]
        public string FileName { get; set; }
    
       // you can add more properties here in the future versions without effecting the existing clients.
    }
    

    服务将实例化并填充并发送回客户端的响应对象:

     [DataContract]
     public class SaveDataSetResponse
     {
        public string Message { get; set; }
     }
    

    服务合同:

    [ServiceContract]
    public interface IDataService
    {
        [OperationContract]
        SaveDataSetResponse SaveDataSet(SaveDataSetRequest request);
    }
    

    及其实现:

    public class DataService : IDataService
    {
        public SaveDataSetResponse SaveDataSet(SaveDataSetRequest request)
        {
            SaveDataSetResponse response = new SaveDataSetResponse();
            try
            {
               // save or processes your data set from request.Data object,
                // once this operation is completed successfully then return the success message.
                response.Message = "Success";
            }
            catch (Exception ex)
            {
                // log your exception 
                response.Message = $"Unable to save / process the data. Reason: {ex.Message}";
            }
    
            return response;
        }
    }
    

    你需要像这样更新服务配置(如果你还没有的话)

    <endpoint
          address="http://localhost:8000/<namespace>/IDataService"
          binding="netTcpBinding"
          contract="<namespace>.IDataService"
          name="DataService">
    </endpoint>
    

    在客户端,更新服务引用(添加新版本的服务dll或服务url - WSDL),创建客户端代理类的实例并调用SaveDataSetResponse SaveDataSet(SaveDataSetRequest request)方法。如果您按原样复制此代码,请确保客户端配置 - 端点也使用新合同进行更新。

    一些有用的链接:

    • 如果您是新手,我会在 WCF 上推荐 the following book 需要刷新:
    • 如果您有多个视线访问权限,那么this course 将是一个不错的选择 起点。

    【讨论】:

    • 非常感谢 :D 你的回答对我很有帮助:) 我会这样做的
    • @SachithMW - 如果您需要进一步的帮助,请告诉我。
    【解决方案3】:

    我解决了我的问题:)

    private void button2_Click(object sender, EventArgs e)
    {
        ServiceReference1.Service2Client obj = new ServiceReference1.Service2Client();
        OpenFileDialog opn = new OpenFileDialog();
        opn.Filter = "Excel Files|*.xls;*.xlsx;*.xlsm";
    
        if (opn.ShowDialog() == DialogResult.Cancel)
            return;
    
        try
        {
            FileStream strm = new FileStream(opn.FileName, FileMode.Open);
            IExcelDataReader excldr = ExcelReaderFactory.CreateOpenXmlReader(strm);
            DataSet rslt = excldr.AsDataSet();
            obj.insertExecl(rslt);
    
        }
        catch (IOException x)
        {
            MessageBox.Show(x.Message);
        }
    }
    

    Service2.cs

    public class Service2 : IService2
    {
        public void insertExecl(DataSet rslt)
        {
            DataClasses1DataContext conn = new DataClasses1DataContext();
    
            foreach (DataTable table in rslt.Tables)
            {
                foreach (DataRow dr in table.Rows)
                {
                    tblExcel addTbl = new tblExcel()
                    {
                        SID = Convert.ToString(dr[0]),
                        Name = Convert.ToString(dr[1]),
                        Address = Convert.ToString(dr[2])
                    };
                    conn.tblExcels.InsertOnSubmit(addTbl);
                }
            }
    
    
            conn.SubmitChanges();
    
            //excldr.Close();
            //strm.Close();
            Console.WriteLine("successfully");
    
        }
    }
    

    IService2.cs

    [ServiceContract]
    public interface IService2
    {
        [OperationContract]
        void insertExecl(DataSet rslt);
    }
    

    【讨论】:

    • 您的代码适用于学校作业,但绝对不能用于生产级应用程序。我建议使用“DataContract”和“DataMemeber”模式将对象传输到 WCF 服务/从 WCF 服务传输。如果您的需求发生变化并且您还需要传递文件名等其他相关信息怎么办?然后,您将更改将对客户端产生连锁反应的方法的签名。仅仅解决问题是一回事,使用最佳实践是另一回事。我鼓励你阅读这个msdn.microsoft.com/en-us/library/ms733832(v=vs.110).aspx
    • @YawarMurtaza 我是 WCF 的新手,我真的不知道你说的这些事情。非常感谢你的评论:) 请告诉我最好的方法是什么而不是我的回答。请给我一个答案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-22
    • 1970-01-01
    • 2014-01-28
    • 2019-07-11
    • 2020-03-16
    • 2020-07-03
    • 1970-01-01
    相关资源
    最近更新 更多