c# - 获取数据行到 C# 对象

标签 c# database class architecture

我有一个 Item 类,它表示列表中的一个项目。我在其中调用返回数据表的存储过程的函数,我需要将数据表转换为项目数组。 这是我所做的:

public class Item
{
    private string _ItemIdDataName = "item_id";
    private string _ItemNameDataName = "item_name";
    private string _PriceDataName = "price";

    public long ItemId { get; set; }
    public string ItemName { get; set; }
    public float Price { get; set; }

    private Item(DataRow row)
    {
        if (row != null)
        {
            ItemId = long.Parse(row[_ItemIdDataName].ToString());
            ItemName = row[_ItemNameDataName].ToString();
            Price = float.Parse(row[_PriceDataName].ToString());
        }
    }

    public Item[] load()
    {
        DataTable dt=DBHandler.GetItems();//Stored procedure that returns DataTable 
        Item[] items = new Item[dt.Rows.Count];
        for (int i = 0; i < dt.Rows.Count; i++)
        {
            items[i] = new Item(dt.Rows[i]);
        }
        return items;
    }
}

我做的对吗? 我该如何改进?

最佳答案

如果您只打算使用它一次,那可能没问题,但如果您要经常使用它,则应该尝试做一些更通用的东西。我写了一篇关于如何为创建对象列表的 DataTable 编写扩展方法的博文。它按照惯例工作,即对象中的属性应与存储过程中的列具有相同的名称(如果可以的话,我会更改存储过程中的名称):

public static class DataTableExtensions
{
    public static IList<T> ToList<T>(this DataTable table) where T : new()
    {
        IList<PropertyInfo> properties = typeof(T).GetProperties().ToList();
        IList<T> result = new List<T>();

        foreach (var row in table.Rows)
        {
            var item = CreateItemFromRow<T>((DataRow)row, properties);
            result.Add(item);
        }

        return result;
    }

    public static IList<T> ToList<T>(this DataTable table, Dictionary<string, string> mappings) where T : new()
    {
        IList<PropertyInfo> properties = typeof(T).GetProperties().ToList();
        IList<T> result = new List<T>();

        foreach (var row in table.Rows)
        {
            var item = CreateItemFromRow<T>((DataRow)row, properties, mappings);
            result.Add(item);
        }

        return result;
    }

    private static T CreateItemFromRow<T>(DataRow row, IList<PropertyInfo> properties) where T : new()
    {
        T item = new T();
        foreach (var property in properties)
        {
            property.SetValue(item, row[property.Name], null);
        }
        return item;
    }

    private static T CreateItemFromRow<T>(DataRow row, IList<PropertyInfo> properties, Dictionary<string, string> mappings) where T : new()
    {
        T item = new T();
        foreach (var property in properties)
        {
            if(mappings.ContainsKey(property.Name))
                property.SetValue(item, row[mappings[property.Name]], null);
        }
        return item;
    }
}

现在你可以调用

var items = dt.ToList<Item>();

var mappings = new Dictionary<string,string>();
mappings.Add("ItemId", "item_id");
mappings.Add("ItemName ", "item_name");
mappings.Add("Price ", "price);
var items = dt.ToList<Item>(mappings);

博文在这里:http://blog.tomasjansson.com/2010/11/convert-datatable-to-generic-list-extension

有很多方法可以扩展它,您可以包含某种映射字典,告诉扩展如何映射列,这样名称就不需要匹配了。或者,您可以添加要在映射中排除的属性名称列表。

更新:您正在创建的对象 (Item) 必须具有默认构造函数,否则私有(private)方法将无法创建它。由于解决方案的工作方式是首先创建对象,而不是使用从反射中获得的属性来设置对象的值。

更新 2: 我添加了带有映射字典的部分,但我自己没有尝试过,所以它可能无法编译。但是,这个概念就在那里,我认为它可行。

关于c# - 获取数据行到 C# 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4593663/

相关文章:

c# - 类型转换对象长

c# - 在 C# 应用程序中存储多个生成的变量值

c# - 如何在 32 个二元期权之间迭代?

sql - 普通英语规范化

C++:指向包含子类的类的父指针

javascript - 如何在 Javascript 对象(类)中使用 setter 和 getter?

c# - 在 C# 中安全回显 MIDI 数据

php - 插入MYSQL失败

php - 从动态 MySql 表中的第 n 行开始获取 m 行

javascript - 扩展 Web API 类构造函数