通用数据映射

时间:2015-06-12 16:43:44

标签: c# asp.net

我试图通过一部分数据检索来熟悉自己的教育目的。我有几个不同的数据模型,我想填充。我没有使用对象关系映射器或为每种形式的检索重建奇异方法,而是考虑了所述方法:

public List<T> BuildModel<T>(string query) where T : new()
{
     var container = new List<T>();
     using(var connection = new SqlConnection(dbConnection))
         using(var command = new SqlCommand(query, connection))
         {
              connection.Open();
              using(var reader = command.ExecuteReader())
                   while(reader.Read())
                   {
                        T model = new T();

                        // How can I associate said data column, to the property in model?

                        container.Add(model);
                   }
         }

      return container;
}

我的方法是否可行,还是我离得很远?我觉得我应该能够访问所说的Anonymous Types来构建模型。我不确定这是可能的,但我觉得应该是这样。如上所述,这是出于教育目的。

2 个答案:

答案 0 :(得分:2)

你最终使用一个ORM(尽管不是一个非常完整的功能),但这是一个非常基本的例子:

public List<T> BuildModel<T>(string query) where T : new()
{
    var container = new List<T>();

    var properties = typeof(T).GetProperties();

    using (var connection = new SqlConnection(dbConnection))
    using (var adapter = new SqlDataAdapter(query, connection))
    {
        connection.Open();

        var table = new DataTable();

        adapter.Fill(table);

        foreach (DataRow row in table.Rows)
        {
            T item = new T();

            foreach (PropertyInfo property in properties)
            {
                if (table.Columns.Contains(property.Name))
                {
                    property.GetSetMethod().Invoke(item, new[] { row[property.Name] });
                }
            }

            container.Add(item);
        }
    }

    return container;
}

这使用反射来尝试查看每个(公共)属性是否作为结果集中的列存在。属性名称必须与列名完全匹配。

假设你有一张桌子Person

create table [Person]
(
    [Id] int not null,
    [FirstName] nvarchar(100) not null,
    [LastName] nvarchar(100) not null
);

以及相应的班级Person

public class Person
{
    public int Id { get; set; }
    public string FirstName { get; set;}
    public string LastName { get; set; }
}

用法是:

var people = BuildModel<Person>("select * from Person");

另外,关于匿名类型 - 我不确定它们是否真的适用于此(你的意思是dynamic?)。如果要返回匿名类型列表,则需要在BuildModel上抛弃类型参数并返回List<object>

答案 1 :(得分:0)

我建立的方法:

private List<T> Build<T>(string query) where T : new()
{
    var container = new List<T>();
    using(var connection = new SqlConnection(dbConnection))
        using(var command = new SqlCommand(query, connection))
        {
            connection.Open();
            using(var reader = command.ExecuteReader())
                while(reader.Read())
                {
                    T model = new T();
                    var columns = Enumerable.Range(0, reader.FieldCount).Select(reader.GetName).ToList();

                    var type = model.GetType();
                    foreach(var property in type.GetProperties())
                        foreach(var column in columns)
                            if (String.Compare(property.Name, column, true) == 0)
                                if(!reader.IsDBNull(reader.GetOrdinal(property.Name)))
                                    property.SetValue(model, reader.GetValue(reader.GetOrdinal(property.Name)), null);

                    container.Add(model);
                }
        }

    return container;
}