【问题标题】:DataSet does not support System.Nullable<> in ExportDataSet 在 Export 中不支持 System.Nullable<>
【发布时间】:2014-06-07 15:16:52
【问题描述】:

我试图使用导出到 Excell、PDF、TextFile 来生成报告。好吧,我在 MVC 中这样做。我有一个名为 SPBatch 的类(这是我的 SQL 中存储过程的确切名称),它包含以下内容:

public string BatchNo { get; set; }
public string ProviderName { get; set; }
public Nullable<System.Int32> NoOfClaims { get; set; }
public Nullable<System.Int32> TotalNoOfClaims { get; set; }
public Nullable<System.Decimal> TotalBilled { get; set; }
public Nullable<System.Decimal> TotalInputtedBill { get; set; }
public Nullable<System.DateTime> DateCreated { get; set; }
public Nullable<System.DateTime> DateSubmitted { get; set; }
public Nullable<System.DateTime> DueDate { get; set; }
public string Status { get; set; }
public string RefNo { get; set; }
public string BatchStatus { get; set; }
public string ClaimType { get; set; }

如您所见,我的一些列被声明为 Nullable。它从搜索和在表格中显示结果顺利进行。我下面有几个按钮是用于导出的图像按钮,每次我尝试在 Excel 中导出时,我总是在这部分代码中遇到问题“DataSet 不支持 System.Nullable” :

foreach (MemberInfo mi in miArray)
{
    if (mi.MemberType == MemberTypes.Property)
    {
        PropertyInfo pi = mi as PropertyInfo;
        dt.Columns.Add(pi.Name, pi.PropertyType); //where the error pop's up.

    }
    else if (mi.MemberType == MemberTypes.Field)
    {
        FieldInfo fi = mi as FieldInfo;
        dt.Columns.Add(fi.Name, fi.FieldType);
    }
}

错误显示在带有注释的那个上。你能帮我做什么吗?我尝试在我的代码中添加 DBNull,但仍然出现相同的错误。我尝试在我的 SPBatch 中删除 Nullable,但我收到一个错误,即需要将某些表声明为 Nullable。

我该怎么办?

【问题讨论】:

  • 我建议不要使用DataSet,因为它似乎不支持您的要求。

标签: c# asp.net-mvc-4 dataset export-to-excel nullable


【解决方案1】:

试试

dt.Columns.Add(pi.Name, Nullable.GetUnderlyingType(
            pi.PropertyType) ?? pi.PropertyType);

【讨论】:

  • 我试过了,但我得到错误“对象引用未设置为对象的实例。” in Columns[column].SetOrdinal(Index);
  • 我在问题的代码示例中看不到这样的代码!
  • 这边好了public void SetColumn(string column, string columnName) { Columns[column].SetOrdinal(Index); //here Columns[column].ColumnName = columnName; Index++; }
  • 请针对您申请中的其他问题提出不同的问题。
  • 好吧,我已经解决了这个问题,您的代码现在运行良好。非常感谢。
【解决方案2】:

由于生成数据表的 C# 版本和一些黑客攻击,我可以在 VB 中提供这个答案 - 我把它放在这里是因为我想从存储的可过滤数据集中获得很多麻烦proc 同时使用一个简单的数据层。我希望它可以帮助别人!

注意:用例是您希望使用 BindingSource.Filter = "some query string":

Imports System.Reflection

Public Module Extenders
<System.Runtime.CompilerServices.Extension>
Public Function ToDataTable(Of T)(collection As IEnumerable(Of T), tableName As String) As DataTable
    Dim tbl As DataTable = ToDataTable(collection)
    tbl.TableName = tableName
    Return tbl
End Function

<System.Runtime.CompilerServices.Extension>
Public Function ToDataTable(Of T)(collection As IEnumerable(Of T)) As DataTable
    Dim dt As New DataTable()

    Dim tt As Type = GetType(T)
    Dim pia As PropertyInfo() = tt.GetProperties()

    'Create the columns in the DataTable

    For Each pi As PropertyInfo In pia
        Dim a = 
If(Nullable.GetUnderlyingType(pi.PropertyType), pi.PropertyType)
        dt.Columns.Add(pi.Name, If(Nullable.GetUnderlyingType(pi.PropertyType), pi.PropertyType))
    Next

    'Populate the table

    For Each item As T In collection
        Dim dr As DataRow = dt.NewRow()
        dr.BeginEdit()

        For Each pi As PropertyInfo In pia

            dr(pi.Name) = If(Nullable.GetUnderlyingType(pi.PropertyType) Is GetType(DateTime), DBNull.Value, pi.GetValue(item, Nothing))
        Next
        dr.EndEdit()
        dt.Rows.Add(dr)
    Next
    Return dt
End Function

End Module

【讨论】:

  • 这很棒。正是我需要的。我确实做了一个小改动,这可能对其他人有用... dr(pi.Name) = If(pi.GetValue(item, Nothing), DBNull.Value) 这似乎允许它在可空的情况下更好地工作日期
【解决方案3】:

我会搜索可为空的并将其替换为可以为空的字符串,与 DateTime 不同。

foreach (PropertyInfo pi in properties)
{
    if (pi.PropertyType.Name.Contains("Nullable"))
       myDataType = typeof(String);
    else
       myDataType = pi.PropertyType;
}

这是一个完整的版本:

private DataTable CreateDataTable(PropertyInfo[] properties)
{
    DataTable dt = new DataTable();
    DataColumn dc = null;
    foreach (PropertyInfo pi in properties)
    {
        dc = new DataColumn();
        dc.ColumnName = pi.Name;

        if (pi.PropertyType.Name.Contains("Nullable"))
            dc.DataType = typeof(String);
        else
            dc.DataType = pi.PropertyType;

        // dc.DataType = pi.PropertyType;
        dt.Columns.Add(dc);
    }
    return dt;
}

【讨论】:

  • 那么,如果基础数据在特定行中包含 DateTime 怎么办?
  • 没有值的可为空的 DateTime 将在 excel 端转换为 NULL。
  • 其实我看到dasmith添加的答案在哪里会更优雅。
  • 它在DataSet中会如何显示?
  • 作为字符串出现
【解决方案4】:

1) 如下定义此扩展

public static class ListExtensions
    {
        public static DataTable ToDataTable<T>(this List<T> list)
        {
            DataTable table = new DataTable(typeof(T).Name);

            //Get Properites of List Fiels
            PropertyInfo[] props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);

            //Create Columns as Fields of List
            foreach (PropertyInfo propertyInfo in props)
            {
                var column = new DataColumn
                {
                    ColumnName = propertyInfo.Name,
                    DataType = propertyInfo.PropertyType.Name.Contains("Nullable") ? typeof(string) : propertyInfo.PropertyType
                };

                table.Columns.Add(column);
            }

            //Fill DataTable with Rows of List
            foreach (var item in list)
            {
                var values = new object[props.Length];

                for (var i = 0; i < props.Length; i++)
                {
                    values[i] = props[i].GetValue(item, null);
                }

                table.Rows.Add(values);
            }


            return table;
        }
    }

2) 调用扩展方法如下,其中 [_lstOperationDetails] 是我们要将其从 List 转换为 DataTable 的 List

DataTable operationDetails = _lstOperationDetails.ToDataTable();

【讨论】:

    猜你喜欢
    • 2013-09-25
    • 1970-01-01
    • 2011-09-09
    • 1970-01-01
    • 1970-01-01
    • 2012-03-16
    • 1970-01-01
    • 2019-05-27
    • 1970-01-01
    相关资源
    最近更新 更多