linq 将数据表转换为列表的通用方法

wsxa1bj1  于 2022-12-06  发布在  其他
关注(0)|答案(3)|浏览(130)

我使用下面的代码:

public static List<T> ConvertToList1<T>(DataTable dt)
        {
            var columnNames = dt.Columns.Cast<DataColumn>()
                    .Select(c => c.ColumnName)
                    .ToList();
            var properties = typeof(T).GetProperties();
            return dt.AsEnumerable().Select(row =>
            {
                T objT1 = Activator.CreateInstance<T>();
                foreach (var pro in properties)
                {
                    if (columnNames.Contains(pro.Name))
                    {
                        PropertyInfo? pI = objT.GetType().GetProperty(pro.Name);
                        pro.SetValue(objT, row[pro.Name] == DBNull.Value ? null : Convert.ChangeType(row[pro.Name], pI.PropertyType));

                    }
                }
                return objT1;
            }).ToList();
        }

但我得到的十进制字段具有空值的错误。

从'System.Decimal'到'System.Nullable'的转换无效1[[System.Decimal,System.Private.CoreLib,版本=6.0.0.0,区域性=中性

public class SampleModel
    {
        public Guid Id { get; set; }
        public Guid ProjectId { get; set; }
        public string? Code { get; set; } = null!;
        public string? Description { get; set; }
        public decimal? Quantity1 { get; set; }
        public decimal? Quantity2 { get; set; }
    }

有人能建议如何解决这个问题吗?

zfciruhq

zfciruhq1#

嗯,阅读一遍......你的意思是说行中的非空小数不能赋给可空小数?还是说dbnull不能赋给可空小数?
您可以使用DataRow.IsNull来检查值是否为dbnull。在这种情况下,您只需跳过它,因为可为null的值已经具有默认null。

// <CODE SNIP />

if (columnNames.Contains(pro.Name))
{
    // if the value was null, just skip it.
    if(!row.IsNull(pro.Name))
    {
        PropertyInfo? pI = objT.GetType().GetProperty(pro.Name);
        pro.SetValue(objT, Convert.ChangeType(row[pro.Name], pI.PropertyType));
    }
}
uajslkp6

uajslkp62#

我有一个剧本。来自@瑞安威尔逊的链接非常有用。
简而言之,如果您有一个可以为null的类型,您希望强制转换为基础类型。请考虑:

decimal? target;
decimal source = 42;
target = source;

这是非常合理的代码,我们可以给decimal?变量赋值。
使用Nullable.GetUnderlyingType(myType)返回一个类型,如果myType不可为空,则返回null。

var underlying1 = Nullable.GetUnderlyingType(target.GetType());
var underlying2 = Nullable.GetUnderlyingType(source.GetType());

这里,underlying2null,并且underlying1decimal
为了将其付诸实践,我们将转换方法的最内层部分稍微修改为:

PropertyInfo pI = objT1.GetType().GetProperty(pro.Name);
var targetType = Nullable.GetUnderlyingType(pI.PropertyType) ?? pI.PropertyType;
pro.SetValue(objT1, row[pro.Name] == DBNull.Value 
  ? null
  : Convert.ChangeType(row[pro.Name], targetType));
jk9hmnmh

jk9hmnmh3#

请尝试以下操作:

public static List<SampleModel> ConvertToList1<T>(DataTable dt)
        {
            List<SampleModel> results = dt.AsEnumerable().Select(x => new SampleModel()
            {
                Id = x.Field<Guid>("Id"),
                ProjectId = x.Field<Guid>("ProjectId"),
                Code = x.Field<string>("Code"),
                Description = x.Field<string>("Description"),
                Quantity1 = x.Field<decimal>("Quantity1"),
                Quantity2 = x.Field<decimal>("Quantity1")
            }).ToList();

            return results;
        }

相关问题