【问题标题】:C# how to populate list of objects from RDBMS without ORMC#如何在没有ORM的情况下从RDBMS填充对象列表
【发布时间】:2021-02-03 07:20:28
【问题描述】:

我想从 DataTable 中填充对象列表,而不是显式地逐列分配数据元素,也不使用 ORM。使用 Dapper(一个小型​​ ORM),可以传递一个 POCO(普通对象)列表,并让它根据该 POCO 的“形状”自动匹配来自查询的“单元格”。我想使用 DataTable 对象做类似的事情。有没有办法在不使用 Dapper 的情况下镜像该功能?我想可以使用反射,但是要使反射可靠地工作通常需要“火箭科学”,尤其是在调试方面。性能是一个相对次要的问题。

public class Employee
{
    public string lastName { get; set; }
    public string firstAndMidName { get; set; }
    public int employeeNumber { get; set; }
    public int salary { get; set; }
}
// ...
public void runSample()
{
    List<Employee> employeeList = new List<Employee>();
    DataTable myDat = queryRDBMS("select * from Employees");  // typical query API (simplified)
    employeeList = convertDataTableToList(myDat, modelClass: Employee);  // the missing part
}

(更新)

【问题讨论】:

  • 是的,你可以。您可以在没有显着性能影响的情况下这样做吗?可能不如 ORM,这也是人们使用它们的原因之一。
  • 您的问题不清楚。您是在询问从数据库中检索数据并用它填充 DataTable 吗?如果是这样,请参阅this answer。否则,请添加更多详细信息,或者可能是显示您遇到问题的代码示例。
  • Dapper 不是 ORM,而是微 ORM。它所做的只是地图属性,没有变化跟踪,所以它非常轻量级。 @DavidL 从属性设置器创建的简单委托字典可以非常快(以前做过),但超出了这里的范围,因为 OP 没有提供任何代码。

标签: c# list datatable data-conversion poco


【解决方案1】:
using System;
using System.Collections.Generic;
using System.Data;
using System.Reflection;

public static class DataTableExtensions
{
    public static List<T> MapToList<T>(this DataTable dt)
    {
        string currentPropName = string.Empty;

        try
        {
            List<T> list = new List<T>();
            T obj = default(T);

            if (dt?.Rows?.Count > 0)
            {
                foreach (DataRow row in dt.Rows)
                {
                    obj = Activator.CreateInstance<T>();
                    foreach (PropertyInfo prop in obj.GetType().GetProperties())
                    {
                        //  Check has column in case we have extension property
                        if (!dt.HasColumn(prop.Name)) continue;
                        currentPropName = prop.Name;

                        if (!object.Equals(row[prop.Name], DBNull.Value))
                        {
                            //  Need to check object type boolean here because return result from db type will be ulong64 which can't convert to bool
                            if (IsBoolean(prop))
                            {
                                prop.SetValue(obj, Convert.ToBoolean(row[prop.Name]), null);
                            }
                            else
                            {
                                prop.SetValue(obj, row[prop.Name], null);
                            }
                        }
                    }

                    list.Add(obj);
                }
            }

            return list;
        }
        catch (Exception ex)
        {
            throw new Exception($"Error occured while converting object '{currentPropName}' from data table to obj class ", ex);
        }
    }

    private static bool IsBoolean(PropertyInfo prop)
    {
        return prop.PropertyType == typeof(bool) || prop.PropertyType == typeof(bool?);
    }

    public static bool HasColumn(this DataTable dt, string columnName)
    {
        for (int i = 0; i < dt.Columns.Count; i++)
        {
            if (dt.Columns[i].ColumnName.Equals(columnName, StringComparison.InvariantCultureIgnoreCase)) return true;
        }

        return false;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-11-22
    • 2015-12-02
    • 1970-01-01
    • 2013-01-05
    • 2013-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多