简体   繁体   English

C# DataTable 到 Object 转换问题

[英]C# DataTable to Object Conversion Issue

I've written a piece of code for converting a DataTable object(which is created from an uploaded excel) to a list of custom object( ExcelTemplateRow in my case).我编写了一段代码,用于将DataTable对象(从上传的 excel 创建)转换为自定义对象list (在我的例子中是ExcelTemplateRow )。 While this method works fine when the values are supplied as expected(in terms of data type of the corresponding column), the code breaks and throws the below error when I try to give a random value(and hence the data type changes):虽然此方法在按预期提供值(根据相应列的数据类型)时工作正常,但当我尝试提供随机值(因此数据类型发生变化)时,代码中断并抛出以下错误:

Object of type 'System.String' cannot be converted to type 'System.Nullable`1[System.Double]'

Below is the method for converting DataTable object to list:下面是将DataTable object转换为列表的方法:

public static List<T> ConvertToList<T>(DataTable dt)
        {
            var columnNames = dt.Columns.Cast<DataColumn>().Select(c => c.ColumnName.ToLower()).ToList();
            var trimmedColumnNames = new List<string>();

            foreach (var columnName in columnNames)
            {
                trimmedColumnNames.Add(columnName.Trim().ToLower());
            }

            var properties = typeof(T).GetProperties();
            return dt.AsEnumerable().Select(row => {
                var objT = Activator.CreateInstance<T>();

                foreach (var property in properties)
                {
                    if (trimmedColumnNames.Contains(property.Name.Trim().ToLower()))
                    {
                        try
                        {
                            if(row[property.Name] != DBNull.Value)
                            {
                                property.SetValue(objT, row[property.Name]);
                            }
                            else
                            {
                                property.SetValue(objT, null);
                            }
                            
                        }
                        catch (Exception ex) 
                        { 
                            throw ex; 
                        }
                    }
                }
                return objT;
            }).ToList();
        }

My custom object looks somewhat like this:我的自定义 object 看起来有点像这样:

 public class ExcelTemplateRow
{
  public string? Country {get; set;}
  public double? Year {get; set;}
  //....
  //....
}

In the excel that I'm uploading, for the Year field, the code works fine when I give proper double values viz 2020, 2021, 2022 etc. but the code breaks when I give something wrong eg 2023g .在我上传的 excel 中,对于Year字段,当我给出正确的双精度值即 2020、2021、2022 等时,代码工作正常2020, 2021, 2022但是当我给出错误的东西时代码会中断,例如2023g It then assumes I'm passing a string and hence the error.然后它假设我传递的是一个字符串,因此是错误的。 I tried by changing the declaration of the Year property to public object? Year {get; set;}我尝试将Year财产声明更改为public object? Year {get; set;} public object? Year {get; set;} public object? Year {get; set;} but it doesn't help. public object? Year {get; set;}但它没有帮助。 I want to make the method robust enough to handle such scenarios.我想让该方法足够强大以处理此类情况。 Any help and I'd be highly grateful.任何帮助,我将不胜感激。

There's a few things to consider here, but I'll try to be as terse as possible.这里有几件事需要考虑,但我会尽量简洁。 When you say:当你说:

but the code breaks when I give something wrong eg 2023g但是当我输入错误时代码会中断,例如 2023g

This means the C# type system is working exactly as intended.这意味着 C# 类型系统完全按预期工作。 A double should never be able to accept the value of "2023g". double 永远不能接受“2023g”的值。 You probably want to store the year as a string instead.您可能希望将年份存储为字符串。 This may involve an intermediate stage of validation, where you import all of your data as a string (ExcelTemplateRow should all be strings in this case).这可能涉及验证的中间阶段,您将所有数据作为字符串导入(在这种情况下,ExcelTemplateRow 应该都是字符串)。

Then your work is ahead of you to validate the data, and then once you've handled any errors, only then can you think about using types such as Double?.然后你的工作就在你面前验证数据,然后一旦你处理了任何错误,你才能考虑使用诸如 Double? 之类的类型。 Although, you probably don't want to store your year as a double, an int might be more appropriate.虽然,您可能不想将年份存储为双精度型,但 int 可能更合适。 Or maybe it isn't;或者也许不是; perhaps you want to store the errors, because that's what a user has entered.也许您想存储错误,因为那是用户输入的内容。 Some careful consideration is required here.这里需要仔细考虑。 Don't rush with the type system, let it work for you, thinking about which datatypes to use will help you design the rest of your code.不要急于使用类型系统,让它为你工作,考虑使用哪些数据类型将有助于你设计代码的 rest。

The issue here is the data coming from the excel, not your code who behave correctly.这里的问题是来自 excel 的数据,而不是行为正确的代码。

Say you try using the T is double?假设您尝试使用T is double? then you double.tryParse(row) and when it fails you take the 4 first caracter of the string 2023g but what will happen if you have another property of type double?然后你double.tryParse(row)当它失败时你取字符串2023g的第 4 个字符但是如果你有另一个double? but expect only 2 or 3 numbers but the user put some dummy stuff how do you will manage that?但期望只有 2 或 3 个数字,但用户放置了一些虚拟的东西,你将如何管理它? It's impossible.不可能。

Fix the Excel not your code;) Log the error, send a message to the user to fix the data:)修复 Excel 不是您的代码;)记录错误,向用户发送消息以修复数据:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM