用fluentdata+webform做一个简单项目(2)-FluentData核心功能

来源:互联网 发布:linux编程获取cpu温度 编辑:程序博客网 时间:2024/06/05 07:35

选择FluentData,主要看中其可以自动将sql查询结果映射为指定对象。

举个例子来讲:

public class Deal {    public int DealId { get; set; }    public string Title { get; set; }    public int FKProviderid { get; set; }    public virtual Provider Provider { get; set; }}public class Provider{    public int ProviderId { get; set; }    public string Name { get; set; }}
使用FluentData如下的语句:

DbContext.Sql("select a.*,b.Name as Provider_Name from Deal a inner join Provider b on a.FKProviderId=b.ProviderId").QueryMany<Deal>();

返回一个List<Deal>并且每个Deal对象的Provider属性都会自动创建为Provider对象,并且为对象的Name赋值

FluentData可以下载到源码,但代码太多不好理解,我在下面实现了sqldatareader映射的功能,大概可以体现FluentData的实现方式:

using System;using System.Collections;using System.Collections.Concurrent;using System.Collections.Generic;using System.Data.SqlClient;using System.Linq;using System.Linq.Expressions;using System.Reflection;using System.Web;/// <summary>/// 反射辅助类/// </summary>public static class ReflectionHelper{    private static readonly ConcurrentDictionary<Type, Dictionary<string, PropertyInfo>> _cachedProperties         = new ConcurrentDictionary<Type, Dictionary<string, PropertyInfo>>();    public static object GetPropertyValue(object item, PropertyInfo property)    {        var value = property.GetValue(item, null);        return value;    }    public static Dictionary<string, PropertyInfo> GetProperties(Type type)    {        var properties = _cachedProperties.GetOrAdd(type, BuildPropertyDictionary);        return properties;    }    private static Dictionary<string, PropertyInfo> BuildPropertyDictionary(Type type)    {        var result = new Dictionary<string, PropertyInfo>();        var properties = type.GetProperties();        foreach (var property in properties)        {            result.Add(property.Name.ToLower(), property);        }        return result;    }    /// <summary>    /// 判断是否是集合    /// </summary>    /// <param name="item"></param>    /// <returns></returns>    public static bool IsList(object item)    {        if (item is ICollection)            return true;        return false;    }    /// <summary>    /// 是否Nullable    /// </summary>    /// <param name="property"></param>    /// <returns></returns>    public static bool IsNullable(PropertyInfo property)    {        if (property.PropertyType.IsGenericType &&            property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))            return true;        return false;    }    /// <summary>    /// Includes a work around for getting the actual type of a Nullable type.    /// 获取属性的类型,若参数可空,返回实际类型。    /// 注:若参数可空,返回如下形式:System.Nullable`1[System.Int32],通过GetGenericArguments()函数获取数组的第一个值即为实际类型    /// </summary>    public static Type GetPropertyType(PropertyInfo property)    {        if (IsNullable(property))            return property.PropertyType.GetGenericArguments()[0];        return property.PropertyType;    }    /// <summary>    /// 创建实例    /// </summary>    /// <param name="type"></param>    /// <returns></returns>    public static object GetDefault(Type type)    {        if (type.IsValueType)            return Activator.CreateInstance(type);        return null;    }    /// <summary>    /// 判断是否是枚举类型,基元类型、值类型、文本类型、日期类型    /// </summary>    /// <param name="type"></param>    /// <returns></returns>    public static bool IsBasicClrType(Type type)    {        if (type.IsEnum            || type.IsPrimitive            || type.IsValueType            || type == typeof(string)            || type == typeof(DateTime))            return true;        return false;    }    /// <summary>    /// 是否是自定义实体类型    /// </summary>    /// <typeparam name="T"></typeparam>    /// <returns></returns>    public static bool IsCustomEntity<T>()    {        var type = typeof(T);        if (type.IsClass && Type.GetTypeCode(type) == TypeCode.Object)            return true;        return false;    }    /// <summary>    /// 获取类型的属性信息    /// </summary>    /// <param name="type"></param>    /// <param name="refresh"></param>    /// <returns></returns>    public static Dictionary<string, PropertyInfo> GetProperties(Type type, bool refresh)    {        try        {            Dictionary<string, PropertyInfo> dicts = new Dictionary<string, PropertyInfo>();            if (!_cachedProperties.TryGetValue(type, out dicts))            {                PropertyInfo[] pis = type.GetProperties();                Dictionary<string, PropertyInfo> dict = new Dictionary<string, PropertyInfo>();                foreach (var pi in pis)                {                    dict.Add(pi.Name, pi);                }                _cachedProperties.TryAdd(type, dict);                _cachedProperties.TryGetValue(type, out dicts);            }            return dicts;        }        catch (Exception ex)        {            throw new ArgumentException("获取属性列表失败:" + ex.Message);        }    }    /// <summary>    /// sdr转换为属性值    /// </summary>    /// <param name="o"></param>    /// <param name="pi"></param>    /// <param name="sdr"></param>    public static void ConvertType<T>(T t, SqlDataReader sdr)    {        try        {            Type type = typeof(T);            var pis = GetProperties(type, false);            List<PropertyInfo> infos = new List<PropertyInfo>();            List<string> subInfos = new List<string>();            for (int i = 0; i < sdr.FieldCount; i++)            {                string colName = sdr.GetName(i).Trim();                PropertyInfo pi;                if (colName.Contains("_"))                {                    subInfos.Add(colName);                    colName = colName.Substring(0, colName.IndexOf("_"));                }                if (pis.TryGetValue(colName, out pi))                {                    infos.Add(pi);                }            }            foreach (var p in infos)            {                if (IsBasicClrType(p.PropertyType))                {                    if (sdr[p.Name] != null)                    {                        if (sdr[p.Name] != DBNull.Value)                        {                            p.SetValue(t, Convert.ChangeType(sdr[p.Name], GetPropertyType(p)), null);                        }                    }                }                else                {                    Type ty = GetPropertyType(p);                    var sub = ConvertType(ty, sdr, p.PropertyType.Name, subInfos);                    p.SetValue(t, Convert.ChangeType(sub, ty), null);                }            }        }        catch(Exception ex)        {            throw new ArgumentException("无法映射属性,属性和sql语句中的字段名称不符:" + ex.Message);        }       }    /// <summary>    /// sdr转换为子属性值    /// </summary>    /// <param name="o"></param>    /// <param name="pi"></param>    /// <param name="sdr"></param>    /// <param name="prefix"></param>    public static object ConvertType(Type type, SqlDataReader sdr, string prefix, List<string> cols)    {        try        {            var pi = GetProperties(type, false);            var obj = Activator.CreateInstance(type);            foreach (var p in pi)            {                var coln = prefix + "_" + p.Value.Name;                if (cols.Contains(coln))                {                    if (sdr[coln] != DBNull.Value)                    {                        p.Value.SetValue(obj, Convert.ChangeType(sdr[coln], p.Value.PropertyType), null);                    }                }            }            return obj;        }        catch        {            throw new ArgumentException("无法映射属性,属性和sql语句中的字段名称不符");        }    }}

测试代码:

using (SqlConnection conn = new SqlConnection("Data Source=.;Initial Catalog=xxxxxx;Persist Security Info=True;User ID=xxxxx;Password=xxxx"))        {            string sql = "select a.Title,b.Name as Provider_Name from Deal a left join Provider b on a.FKProviderId=b.ProviderId";            SqlCommand sc = new SqlCommand(sql, conn);            List<Deal> deals = new List<Deal>();            conn.Open();            SqlDataReader reader = sc.ExecuteReader();            while (reader.Read())            {                Deal deal = new Deal();                ReflectionHelper.ConvertType<Deal>(deal, reader);                deals.Add(deal);            }            reader.Close();            GridView1.DataSource = deals;            GridView1.DataBind();        }

实现的功能有限,用于说明fluentdata的部分原理,希望能抛砖引玉

0 0