由于内部错误,服务器无法处理该请求。有关该错误的详细信息,请打开服务器上的 IncludeExceptionDetailInFaults (从 ServiceBehaviorAttribute 或从 配置行为)以便将异常信息发送回客户端,或打开对每个 Microsoft .NET Framework SDK 文档的跟踪并检查服务器跟踪日志。

时间:2021-06-16 03:30:38

客户端调用WCF的时候报上面的错误,WCF只能序列化基础的数据类型,不能直接序列化SqlParameter类型,需要使用自定义类,然后在WCF服务端转换的方式解决:

自定义类代码如下:

 1 using System;
2 using System.Collections.Generic;
3 using System.Data;
4 using System.Data.SqlClient;
5 using System.Linq;
6 using System.Runtime.Serialization;
7 using System.Text;
8 using System.Threading.Tasks;
9
10 namespace CommonLib.CustomClass
11 {
12 /// <summary>
13 /// 方法标记为DataContract约束,属性标记为DataMember
14 /// </summary>
15 [Serializable]
16 [DataContract]
17 public class SetSqlParameter
18 {
19 #region 属性
20
21 /// <summary>
22 /// 参数名称
23 /// </summary>
24 [DataMember]
25 private string paraName = "";
26 public string ParaName
27 {
28 get { return this.paraName; }
29 set { this.paraName = value; }
30
31 }
32
33
34 /// <summary>
35 /// 参数长度
36 /// </summary>
37 [DataMember]
38 private int paraLength = 0;
39 public int ParaLength
40 {
41
42 get { return this.paraLength; }
43 set { this.paraLength = value; }
44 }
45
46
47 /// <summary>
48 /// 参数值
49 /// </summary>
50 [DataMember]
51 private object paraValue = null;
52 public object ParaValue
53 {
54 get { return this.paraValue; }
55 set { this.paraValue = value; }
56 }
57
58
59 /// <summary>
60 /// 参数类型
61 /// </summary>
62 [DataMember]
63 private SqlDbType paraDbType = SqlDbType.NVarChar;
64 public SqlDbType ParaDbType
65 {
66 get { return this.paraDbType; }
67
68 set { this.paraDbType = value; }
69 }
70
71 #endregion
72
73 /// <summary>
74 /// 构造函数
75 /// </summary>
76 /// <param name="sPara"></param>
77 public SetSqlParameter(SqlParameter sPara)
78 {
79 this.paraName = sPara.ParameterName;
80 this.paraLength = sPara.Size;
81 this.paraValue = sPara.Value;
82 this.paraDbType = sPara.SqlDbType;
83 }
84
85 /// <summary>
86 /// 转换成SqlParameter类型
87 /// </summary>
88 /// <returns></returns>
89 public SqlParameter ConvertToSqlParameter()
90 {
91 SqlParameter parameter = new SqlParameter(this.paraName, this.paraDbType, this.paraLength);
92 parameter.Value = this.paraValue;
93 return parameter;
94 }
95 }
96 }

WCF服务端代码如下:

接口代码:

 1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Runtime.Serialization;
5 using System.ServiceModel;
6 using System.Text;
7 using System.Data;
8 using System.Data.SqlClient;
9 using CommonLib.CustomClass;
10
11 namespace WcfServiceDemo
12 {
13 // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“IMyService”。
14 [ServiceContract]
15 public interface IMyService
16 {
17 [OperationContract]
18 DataTable ExeceteQuery(string strSQL, params SetSqlParameter[] parameters);
19 }
20 }

接口实现类代码:

 1 using System;
2 using System.Collections.Generic;
3 using System.Data;
4 using System.Data.SqlClient;
5 using System.Linq;
6 using System.Runtime.Serialization;
7 using System.ServiceModel;
8 using System.Text;
9 using System.Configuration;
10 using CommonLib.CustomClass;
11
12 namespace WcfServiceDemo
13 {
14 // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码、svc 和配置文件中的类名“MyService”。
15 // 注意: 为了启动 WCF 测试客户端以测试此服务,请在解决方案资源管理器中选择 MyService.svc 或 MyService.svc.cs,然后开始调试。
16 public class MyService : IMyService
17 {
18
19 public DataTable ExeceteQuery(string strSQL, params SetSqlParameter[] parameters)
20 {
21 DataTable dtReturn = new DataTable();
22 dtReturn.TableName = "ExecuteQuery";
23 string strCon = ConfigurationManager.ConnectionStrings["HealthHospInfection"].ConnectionString;
24 using (SqlConnection conn = new SqlConnection(strCon))
25 {
26 SqlCommand cmd = new SqlCommand(strSQL, conn);
27 conn.Open();
28 if (parameters != null)
29 {
30 SqlParameter[] para = new SqlParameter[parameters.Length];
31 for (int i = 0; i < parameters.Length; i++)
32 {
33 //把SetSqlParameter类型的数组转换成SqlParameter类型的数组
34 para[i] = parameters[i].ConvertToSqlParameter();
35 }
36 cmd.Parameters.AddRange(para);
37 }
38
39 SqlDataAdapter adapter = new SqlDataAdapter(cmd);
40 adapter.Fill(dtReturn);
41 }
42 return dtReturn;
43 }
44 }
45 }

客户端调用WCF代码:

 1 using CommonLib.CustomClass;
2 using System;
3 using System.Collections.Generic;
4 using System.ComponentModel;
5 using System.Data;
6 using System.Data.SqlClient;
7 using System.Drawing;
8 using System.Linq;
9 using System.Text;
10 using System.Threading.Tasks;
11 using System.Windows.Forms;
12
13
14 namespace winClient
15 {
16 public partial class Form1 : Form
17 {
18 public Form1()
19 {
20 InitializeComponent();
21 }
22
23 private void btn_GetData_Click(object sender, EventArgs e)
24 {
25
26 string strSQL = " SELECT * FROM BaseSetMainInfo WHERE TypeCode=@TypeCode ";
27
28 //定义SqlParameter
29 SqlParameter para = new SqlParameter("@TypeCode", SqlDbType.Int);
30 para.Value = 1;
31
32 //定义SetSqlParameter类型的数组
33 SetSqlParameter[] paras = new SetSqlParameter[] {
34 new SetSqlParameter(para)
35 };
36
37 //实例化WCF服务
38 ServiceReference.MyServiceClient client=new ServiceReference.MyServiceClient();
39 //调用WCF服务提供的方法
40 DataTable dt = client.ExeceteQuery(strSQL, paras);
41 this.dataGridView1.DataSource = dt;
42
43 }
44 }
45 }

这样就可以解决WCF不能直接序列化SqlParameter类型的问题了。

代码下载地址:https://files.cnblogs.com/files/dotnet261010/WcfSqlParameterDemo.rar