C#.NET IDataReader扩展 ToList<T>/Get<T>

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Data;
using System.Data.Common;
using System.Web.Script.Serialization;
using System.IO;
using System.Security.Cryptography;

namespace Pub.Class {
public static class IDataReaderExtensions {

public static List<TResult> ToList<TResult>(this IDataReader dr) where TResult : class,new() {
List
<TResult> list= new List<TResult>();
if (dr == null) return list;
int len = dr.FieldCount;

while (dr.Read()) {
TResult info
= new TResult();
for (int j = 0; j < len; j++) {
if (dr[j] == null || string.IsNullOrEmpty(dr[j].ToString())) continue;
System.Reflection.PropertyInfo pi
= info.GetType().GetProperty(dr.GetName(j).Trim());
pi.SetValue(info, dr[j],
null);
}
list.Add(info);
}
dr.Close(); dr.Dispose(); dr
= null;
return list;
}

public static T Get<T>(this IDataReader reader, string field) {
return reader.Get<T>(field, default(T));
}
public static T Get<T>(this IDataReader reader, string field, T defaultValue) {
var value
= reader[field];
if(value == DBNull.Value) return defaultValue;
return value.ConvertTo<T>(defaultValue);
}

}
}

 

调用实例:

public virtual IList<EC_Type> SelectListByAll(string order, string fieldList, bool useCache) {
string cacheKey = string.Format("EC_TypeCache_SelectListByAll_{0}_{1}", order, fieldList); IList<EC_Type> list = null;
if (useCache) {
list
= (IList<EC_Type>)Cache2.Get(cacheKey);
if (list != null) return list;
}

DbParameter[] dbParams
= {
Data.MakeInParam(
"@Fields", (DbType)SqlDbType.VarChar, 1000, fieldList),
Data.MakeInParam(
"@Order", (DbType)SqlDbType.VarChar, 100, order),
};
list
= Data.GetDbDataReader("EC_Type_SelectListByAll", dbParams).ToList<EC_Type>();
if (useCache) Cache2.Insert(cacheKey, list, cacheSeconds);
return list;
}

 

 

 

posted @ 2010-08-16 21:02 熊哥 阅读(2519) 评论(12) 编辑 收藏

 回复 引用 查看   
#1楼2010-07-06 15:56 | 温景良(Jason)      
这扩展不错,有意思
 回复 引用 查看   
#2楼2010-07-06 16:25 | 梦幻天涯      
不错, 不过可参照一下ETLB中的Data Access那块, 扩展一个Mapping会好一些,毕竟一一对应的数据结果不常见。
 回复 引用 查看   
#3楼2010-07-06 18:11 | 风云      
对比一下呵呵。。。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Reflection.Emit;
using System.Reflection;
using NLite.Reflection;

namespace NLite.Conversion
{
    public static  class DataReaderConverter
    {
        private static readonly BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;

        struct Mapping
        {
            public Type SourceType;
            public Type TargetType;

            public FieldInfo Field;
            public MethodInfo Method;

        }

        public static IEnumerable<T> Convert<T>(this IDataReader dataRecord) where T:new()
        {
            var items = new List<T>();
            var mappings = CreateMappings<T>(dataRecord);

            while (dataRecord.Read())
            {
                var item = new T();
                items.Add(item);

                foreach (var i in mappings.Keys)
                {
                    if (dataRecord.IsDBNull(i))
                        continue;

                    var m = mappings[i];
                    var value = ConverterManager.Convert(dataRecord[i], m.SourceType, m.TargetType);

                    if (m.Field != null)
                        m.Field.Set(item, value);
                    else
                        m.Method.FastInvoke(item, value);
                }
            }

            return items;
        }

        private static Dictionary<int, Mapping> CreateMappings<T>(IDataReader dataRecord) where T : new()
        {
            var mappings = new Dictionary<int, Mapping>();
            var fieldCount = dataRecord.FieldCount;
            var elementType = typeof(T);

            for (int i = 0; i < fieldCount; i++)
            {
                var columnName = dataRecord.GetName(i);
                var mapping = new Mapping { SourceType = dataRecord.GetFieldType(i) };

                var method = elementType.GetMethod("set_" + columnName, flags);
                if (method != null)
                {
                    mapping.Method = method;
                    mapping.TargetType = method.GetParameters()[0].ParameterType;
                    mappings.Add(i, mapping);

                }
                else
                {
                    mapping.Field = elementType.GetField(columnName, flags);
                    if (mapping.Field != null)
                    {
                        mapping.TargetType = mapping.Field.FieldType;
                        mappings.Add(i, mapping);
                    }
                }


            }
            return mappings;
        }
    }
}


 回复 引用 查看   
#4楼[楼主]2010-07-06 22:33 | 熊哥      
引用风云:
对比一下呵呵。。。
[code=csharp]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Reflection.Emit;
using System.Reflection;
using NLite.Reflection;

namespace NLite.Conversion
{
public static class DataReaderConverter
{
...

嗯写的不错

 回复 引用 查看   
#5楼2010-07-08 11:17 | Zhenway      
提两个建议
1.如果作为基础类库,反射的代价显得高了点
2.关闭DataReader还是采用谁打开谁关闭的原则好一点(例如在一个Reader中返回两个表)

 回复 引用 查看   
#6楼2010-08-16 21:04 | 《小YY》      
建议你做一个反射缓存池。

这样一次性的反射 N次使用 性能体幅度提高。

 回复 引用 查看   
#7楼[楼主]2010-08-16 21:09 | 熊哥      
引用《小YY》:
建议你做一个反射缓存池。

这样一次性的反射 N次使用 性能体幅度提高。


谢谢下一个版本将改进这个。:)

 回复 引用 查看   
#8楼2010-08-17 08:47 | 高天乐      
关注ing,楼主的code相当有用,呵呵
 回复 引用 查看   
#9楼2010-08-17 09:02 | 《小YY》      
又看了一下,,,异常处理
 回复 引用 查看   
#10楼2010-08-17 09:09 | 鹤冲天      
思路很好
 回复 引用 查看   
#11楼2010-08-17 10:35 | 梦幻天涯      
ETLB那个是相当的慢啊
 回复 引用 查看   
#12楼2011-07-27 11:39 | cxlings      
(useCache) Cache2.Insert(cacheKey, list, cacheSeconds);