麻烦各位了,看有没有碰到过这个的,DataSet序列化报错,错误信息为:System.Runtime.Serialization.SerializationException:“内部数组不能扩展到大于 Int32.MaxValue 个元素。”
DataSet为包含30万条数据且列为180列的一张表,在进行序列化时报错,求解决方案,google,百度好久好像都说是C#的序列化BUG,麻爪中......,DataSet数据减少就算了,这是客户进行数据统计分析的一个操作,需要把大批量的数据全部加载并显示由客户进行处理,实际数据量可能比这个还要大,至于序列化是因为需要通过Remoting进行数据传输,将数据传到客户端减少流量消耗,以下代码是一简单Demo代码,同样会触发该BUG!
1 static void Main(string[] args) 2 { 3 DataSet ds = new DataSet(); 4 DataTable dt = new DataTable(); 5 for (int i = 0; i < 180; i++) 6 { 7 DataColumn dc = new DataColumn(); 8 dc.ColumnName = "Column_" + i.ToString(); 9 dc.DefaultValue = "Test_" + i.ToString(); 10 dt.Columns.Add(dc); 11 } 12 DateTime bft = DateTime.Now; 13 for (int i = 0; i < 300000; i++) 14 { 15 DataRow dr = dt.NewRow(); 16 for (int j = 0; j < 180; j++) 17 { 18 dr[j] = "Row_" + i.ToString() + "_Column_" + j.ToString(); 19 } 20 dt.Rows.Add(dr); 21 } 22 DateTime aft = DateTime.Now; 23 TimeSpan nspan = aft.Subtract(bft); 24 Console.WriteLine("添加300000条数据总共花费{0}ms.,{1}s,{2}m", nspan.TotalMilliseconds,nspan.TotalSeconds,nspan.TotalMinutes); 25 ds.Tables.Add(dt); 26 byte[] bArrayResult = null; 27 try 28 { 29 ds.RemotingFormat = SerializationFormat.Binary; 30 MemoryStream ms = new MemoryStream(); 31 IFormatter bf = new BinaryFormatter(); 32 bf.Serialize(ms, ds); 33 bArrayResult = ms.ToArray(); 34 ms.Close(); 35 Console.WriteLine("DataSet文件大小:"+GetFileSize(bArrayResult.LongLength)); 36 } 37 catch (Exception ex) 38 { 39 throw ex; 40 } 41 } 42 43 /// <summary> 44 /// 计算文件大小函数(保留两位小数),Size为字节大小 45 /// </summary> 46 /// <param name="size">初始文件大小</param> 47 /// <returns></returns> 48 public static string GetFileSize(long size) 49 { 50 var num = 1024.00; //byte 51 if (size < num) 52 return size + "B"; 53 if (size < Math.Pow(num, 2)) 54 return (size / num).ToString("f2") + "K"; //kb 55 if (size < Math.Pow(num, 3)) 56 return (size / Math.Pow(num, 2)).ToString("f2") + "M"; //M 57 if (size < Math.Pow(num, 4)) 58 return (size / Math.Pow(num, 3)).ToString("f2") + "G"; //G 59 return (size / Math.Pow(num, 4)).ToString("f2") + "T"; //T 60 }
有这问题的不止是DataSet序列化,转换为List或Hashtable序列化都是一样,只要数据列180左右行10万左右必定报这个错误!
/// <summary>
/// Table2Model
/// </summary>
public static class Table2Model {
#region 公共方法(扩展DataTable)
/// <summary>
/// DataTable转换成T
/// </summary>
/// <typeparam name="T">实体类型</typeparam>
/// <param name="table">需转换的数据table</param>
/// <returns></returns>
public static T ToModel<T>(this DataTable table) where T : new() {
T entity = new T();
foreach (DataRow row in table.Rows) {
foreach (var item in entity.GetType().GetProperties()) {
if (row.Table.Columns.Contains(item.Name)) {
if (DBNull.Value != row[item.Name]) {
item.SetValue(entity, ChangeType(row[item.Name], item.PropertyType), null);
}
}
}
}
return entity;
}
/// <summary>
/// DataTable转换成T
/// </summary>
/// <typeparam name="T">实体类型</typeparam>
/// <param name="table">需转换的数据table</param>
/// <param name="ext">外延表重名需加的前缀</param>
/// <returns></returns>
public static T ToModel<T>(this DataTable table, string ext) where T : new() {
T entity = new T();
foreach (DataRow row in table.Rows) {
foreach (var item in entity.GetType().GetProperties()) {
if (row.Table.Columns.Contains(ext + item.Name)) {
if (DBNull.Value != row[ext + item.Name]) {
item.SetValue(entity, ChangeType(row[ext + item.Name], item.PropertyType), null);
}
}
}
}
return entity;
}
/// <summary>
/// DataTable转换成List<T>
/// </summary>
/// <typeparam name="T">实体类型</typeparam>
/// <param name="table">需转换的数据table</param>
/// <returns></returns>
public static List<T> ToModelList<T>(this DataTable table) where T : new() {
List<T> entities = new List<T>();
foreach (DataRow row in table.Rows) {
T entity = new T();
foreach (var item in entity.GetType().GetProperties()) {
if (row.Table.Columns.Contains(item.Name)) {
if (DBNull.Value != row[item.Name]) {
item.SetValue(entity, ChangeType(row[item.Name], item.PropertyType), null);
}
}
}
entities.Add(entity);
}
return entities;
}
#endregion 公共方法(扩展DataTable)
#region 私有方法(Convert.ChangeType处理Nullable<>和非Nullable<>)
/// <summary>
/// 类型转换(包含Nullable<>和非Nullable<>转换)
/// </summary>
/// <param name="value"></param>
/// <param name="conversionType"></param>
/// <returns></returns>
private static object ChangeType(object value, Type conversionType) {
// Note: This if block was taken from Convert.ChangeType as is, and is needed here since we're
// checking properties on conversionType below.
if (conversionType == null) {
throw new ArgumentNullException("conversionType");
} // end if
// If it's not a nullable type, just pass through the parameters to Convert.ChangeType
if (conversionType.IsGenericType &&
conversionType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) {
if (value == null) {
return null;
} // end if
// It's a nullable type, and not null, so that means it can be converted to its underlying type,
// so overwrite the passed-in conversion type with this underlying type
System.ComponentModel.NullableConverter nullableConverter = new System.ComponentModel.NullableConverter(conversionType);
conversionType = nullableConverter.UnderlyingType;
} // end if
// Now that we've guaranteed conversionType is something Convert.ChangeType can handle (i.e. not a
// nullable type), pass the call on to Convert.ChangeType
return Convert.ChangeType(value, conversionType);
}
#endregion 私有方法(Convert.ChangeType处理Nullable<>和非Nullable<>)
}
看看能够满足你要不
一样还是有问题,数据量只要到一定的大小还是会报错
@sunkejava: 如果是数据量过大,那么我建议你可以把dateset拆分一下,分别序列化以后,在合并为结果
不好搞啊,客户电脑内存太小,哪怕服务器端数据能查出来,分次也能传输到客户端,但是一合并就会造成溢出,没办法了只能减少列或者分页了,太坑了
你不是开玩笑吧,序列化 DataSet ?
开啥玩笑,历史遗留所有数据全都是用DataSet接收处理的,要改其他的牵扯太大,不敢动
@sunkejava: 是否可以尝试分页处理一下?
@申龙斌的程序人生: 不行,这是一个客户进行前台统计分析操作的页面,需要加载出全部符合条件的数据进行统一分析
@sunkejava: 那么大的数据量用户分析啥,不能下载吗?要在页面加载?
不能直接序列化 DataSet,要先保存成为文件:
/// <summary>
/// 序列和反序列 DataSet
/// </summary>
public static void SerializeDataSet()
{
//测试数据
DataSet ds = new DataSet();
DataTable dt = GetTestData();
ds.Tables.Add(dt);
//序列化
FileStream fs = new FileStream("ds.data", FileMode.Create);
BinaryFormatter bf = new BinaryFormatter();
ds.RemotingFormat = SerializationFormat.Binary;
bf.Serialize(fs, ds);
fs.Close();
//清空 DataSet
ds.Clear();
fs = new FileStream("ds.data", FileMode.Open);
//反序列化
DataSet newDs = (DataSet)bf.Deserialize(fs);
}
/// <summary>
/// 获取测试数据
/// </summary>
/// <returns></returns>
private static DataTable GetTestData()
{
DataTable dtTable = new DataTable();
//建立字段
dtTable.Columns.Add("filed1", typeof(int));
dtTable.Columns.Add("filed2", typeof(string));
dtTable.Columns.Add("filed3", typeof(bool));
dtTable.Columns.Add("filed4", typeof(DateTime));
DataRow row;
for (int i = 1; i < 10; i++)//新增测试数据
{
row = dtTable.NewRow();
row["filed1"] = i;
row["filed2"] = "字符串" + i.ToString();
row["filed3"] = i % 2 == 0;
row["filed4"] = DateTime.Now;
dtTable.Rows.Add(row);
}
return dtTable;
}
测试了下,不行,你拿180列100000条左右的数据试下,还是会有那个提示
@sunkejava: 不要用dataset,使用list
@三人乐乐: 用过List了,结果一样,好像C#序列化超过一定大小之后就是会一直报这个错,除非数据量减少
开个线程分页传输就好了,界面搞个提示框等待中,后台等全部传输完成一起展示,这样不管你有多少数据都没事