用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
- 用fluentdata+webform做一个简单项目(2)-FluentData核心功能
- 用fluentdata+webform做一个简单项目(1)-组织结构
- FluentData
- FluentData
- FluentData介绍
- 微型 ORM-FluentData
- 微型 ORM-FluentData
- FluentData官方文档翻译
- 微型 ORM-FluentData 温故知新系列
- 微型 ORM-FluentData 实例详解
- 新型轻量级ORM FluentData的使用
- FluentData - 轻量级.NET ORM持久化技术解决方案
- FluentData - 轻量级.NET ORM持久化技术解决方案
- FluentData 轻量级.NET ORM持久化技术详解
- 如何做一个简单的开放接口(2)-核心引擎(上)
- 【ionic】做一个简单的 card功能
- 如何做一个简单的开放接口(3)-核心引擎(下)
- WebForm写一个简单的登录
- 面向接口编程的意义
- hdu ---2029做题笔记(c++)
- redis 主从配置的作用是什么
- go linux install & config
- curl的get使用方式
- 用fluentdata+webform做一个简单项目(2)-FluentData核心功能
- 什么导致了Context泄露:Handler&内部类
- 使用mock模块来帮助python测试
- Tomcat无法启动但不报错原因分析
- 第七周 项目2 建立链队算法库
- localhost 不能在 IE打开问题
- Tips for debugging on Linux
- 代理模式设计只能内网访问线上数据库
- 利用dragonboard 410c开发版快速搭建你的智能安全监控摄像头