0

在这个项目中,用户将有机会创建具有属性的对象数组,这些属性与数据库表匹配,对象的属性与数据库电缆中的列相同。SQL 看起来像:

create table ServiceData
(ServiceId int
,ServiceDescription varchar(50)
)
go
create type ServiceType as table
(ServiceId int
,ServiceDescription varchar(50)
)
go
create proc spInsertService
@service ServiceType readonly
as
begin
    insert into ServiceData(ServiceId,ServiceDescription)
    select * from @service
end

在这里,我创建了一个自定义类型并将该自定义类型以表值参数的形式传递给存储过程。SQL 和以下 C# 代码执行并正常工作:

[WebMethod]
        public void InsertServiceData()
        {
            List<ServiceData> sdList = new List<ServiceData>();
            ServiceData sd1 = new ServiceData(1, "first");
            ServiceData sd2 = new ServiceData(2, "second");
            sdList.Add(sd1);
            sdList.Add(sd2);
            DataTable dt = new DataTable();
            dt.Columns.Add("ServiceId");
            dt.Columns.Add("ServiceDescription");
            foreach (var data in sdList)
            {
                dt.Rows.Add(data.ServiceId, data.ServiceDescription);
            }
            string cs = ConfigurationManager.ConnectionStrings["dbcs"].ConnectionString;
            using (var con = new SqlConnection(cs))
            {
                using (var cmd = new SqlCommand("spInsertService",con))
                {
                    con.Open();
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.Parameters.AddWithValue("@service", dt);
                    cmd.ExecuteNonQuery();
                }
            }
        }

您可以看到,在这个工作示例中,我没有使用任何 AJAX 调用将数据发送到 Web 方法。此代码当前可以正常工作并从该硬编码列表中插入数据。因此,当我更改代码以实际尝试采用这样的 JavaScript 数组时:

 $(document).ready(function ()
        {
            sd1 = {};
            sd1.ServiceId = 1;
            sd1.ServiceDescription = "test";

            sd2 = {};
            sd2.ServiceId = 2;
            sd2.ServiceDescription = "other test";
            //create array which is meant to mirror the List<ServiceData> in the 
            //earlier example
            service = new Array();
            service.push(sd1);
            service.push(sd2);
            //wrap the array in a data transfer object
            var dto = {'sdList': service};
            $('#btnSubmit').click(function ()
            {
                $.ajax(
                {
                    type: "POST",
                    url: "WebService.asmx/InsertServiceData",
                    contentType: "application/json",
                    dataType: "json",
                    //stringify the dto
                    data: JSON.stringify(dto),
                    success: function(data)
                    {
                        console.log('success');
                    },
                    error: function(thrownError)
                    {
                        console.log(thrownError);
                    }
                });
            });
        });

新的 C#

[WebMethod]
        //this attempts to deserialize the DTO into a list of ServiceData objects
        //which are then inserted into the TVP and then to the database

        public void InsertServiceData(string sdList)
        {
            var jss = new JavaScriptSerializer();
            List<ServiceData> list = jss.Deserialize<List<ServiceData>>(sdList);
            DataTable dt = new DataTable();
            dt.Columns.Add("ServiceId");
            dt.Columns.Add("ServiceDescription");
            foreach (var data in list)
            {
                dt.Rows.Add(data.ServiceId, data.ServiceDescription);
            }
            string cs = ConfigurationManager.ConnectionStrings["dbcs"].ConnectionString;
            using (var con = new SqlConnection(cs))
            {
                using (var cmd = new SqlCommand("spInsertService",con))
                {
                    con.Open();
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.Parameters.AddWithValue("@service", dt);
                    cmd.ExecuteNonQuery();
                }
            }
        }

目前该代码给了我错误:Type\u0027System.String\u0027isnotsupportedfordeserializationofanarray 如果我不将数组包装在 DTO 对象中,但仍然将其字符串化,我会得到

`System.Collections.Generic.IDictionary`2[[System.String,mscorlib,Version=4.0.0.0,Culture=neutral,PublicKeyToken`

我不想为此使用 ViewState 的 SessionState。因为我知道如果我没有将 JavaScript 数组传递给 WebMethod,代码可以正常工作,所以它必须在破坏它的数组的序列化和反序列化中的某个地方。我怎样才能解决这个问题?这几天让我发疯

4

1 回答 1

0

请注意以下步骤,然后更改您的代码行。

  1. 不要创建sd1={}sd2{}.
  2. var list = [];在顶部创建然后推送 json 对象,如list.push({"ServiceId":1,"ServiceDescription":"test"}, {"ServiceId":2,"ServiceDescription":"other test"})
  3. 创建类似的ajax参数var data = "{'sdLists':" +JSON.stringify(list)+"}";并将日期作为参数传递。
  4. 创建一个带有变量的 bean,以映射上面列表中添加的 json 对象。见打击。

    公共类 SdList { 私有 int Serviceid; 公共 int Serviceid { 获取 { 返回 Serviceid; } 设置 { Serviceid= 值;} } 私有字符串服务描述;公共字符串服务描述 { 获取 { 返回服务描述;} 设置 { 服务描述 = 值;} } }

  5. 现在List<SdList> sdLists作为参数列表传递给方法如下

    var data = "{'sdLists':"+JSON.stringify(list)+"}"; 公共无效插入服务数据(列出 sdLists)

  6. 然后使用 java 脚本序列化程序将 Json 列表转换为通用列表,如下所示, JavaScriptSerializer jss= new JavaScriptSerializer();

    List<SdList> list = jss.ConvertToType<List<SdList>>(sdLists);

我已按照上述步骤操作,并且工作正常。

于 2013-11-27T06:30:10.377 回答