用fluentdata+webform做一个简单项目(2)-FluentData核心功能
2016-10-13 15:01
549 查看
选择FluentData,主要看中其可以自动将sql查询结果映射为指定对象。
举个例子来讲:
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 (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的部分原理,希望能抛砖引玉
举个例子来讲:
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的部分原理,希望能抛砖引玉
相关文章推荐
- 用fluentdata+webform做一个简单项目(1)-组织结构
- 基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍。最后我们将会实现一个基于Server-Sent Event和Flask简单的在线聊天室。
- 基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍。最后我们将会实现一个基于Server-Sent Event和Flask简单的在线聊天室。
- nodejs 利用express框架 创建一个简单的web项目
- intellij idea和maven结合的简单实用,部署一个web项目
- 【Java.Web】创建一个简单的Java Web项目
- 简单的spring-data集成mongoDB项目,实现crud的功能
- 为您的Web项目构建一个简单的JSON控制器
- 如何使用 asp.net 4.0 新特性 路由功能 有助于seo优化 给一个 asp.net web项目(网站项目) 增加路由功能 ,继承,给根据路由生成的url的结尾,增加一个有利于seo优化的斜杠 /,跳转到一个路由生成的url页面
- 解决一个web项目的某个功能的流程
- JavaEE完全实战详解笔记--在Eclipse中创建一个简单的web项目
- Applet 实现一个简单的web流程图或拓扑图绘制功能
- WebUserControl的简单用法,最近的几个项目都反复用到TextBox,CheckBox,RadiobuttonList,所以玩一下webusercontrol,有个投票功能哦。
- 简单实现一个Form窗体的抖动功能
- 一个最简单的java web项目的部署
- Jsp 入门 - 一个简单的web项目
- 一个简单的web项目
- 一个简单的ASP.NET WebForm "Model Binder"
- Asp.Net MVC3 简单入门第一季(五) 通过Asp.Net MVC的区域功能实现将多个MVC项目部署到一个站点
- 一个简单的javaweb项目包含的东西