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