自己动手写ORM框架(六):实现查询功能FindById方法

    通过配置实体与表的关系映射后,就可以实现对表的操作了,接下来实现简单对象的新增功能。下面代码1-1是定义的操作数据对象方法的接口:

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;

 System.Orm.EntityManager
{
    public  
    {
       
         Transaction { get; set; }
       
        
        <T> FindAll<T>() where T : (); 
 
        
<T> FindBySql<T>( strSql) where T : (); 
 
        
        <T> FindById<T>( id) where T : (); 
       
       
        int Save<T>(T entity);

       
        int Update<T>(T entity);

       
        int Remove<T>(T entity);

       
        int Remove<>( id) where  : ();
    }
}

    下面先实现比较简单的查询方法,代码1-2:

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Orm.CustomAttributes;
using System.Data.SqlClient;
using System.Collections;
using System.Data;
using System.Orm.DBUtility;
using System.Orm.Common;

namespace System.Orm.EntityManager
{
    public class  : 
    {
        //......实现EntityManager接口...                               
    }
}

    下面是PropertyImpl 类中FindById方法的代码1-3:

 通过主键ID查询数据
public <T> FindById<T>(object id)   : new()
{
    <T> listArr = new <T>();
 
    
   type =  ().GetType();
 
    
    [] properties = .GetProperties(type);
    
    
     tableInfo = .GetTableInfo(type, .SELECT);
    
    
    String strSql = .GetFindByIdSql(tableInfo);

    
    [] parms = .CreateDbParameters(1);
    parms[0].ParameterName = tableInfo.Id.Key;
    parms[0].Value = id;            

     sdr = null;
    try
    {
        sdr = .ExecuteReader(.ConnectionString, .Text, strSql, parms);
        while (sdr.Read())
        {
            
               entity = new ();
            foreach ( property in properties)
            {
              
                name = tableInfo.PropToColumn[property.Name].ToString();
              
              
                .SetPropertyValue(entity, property, sdr[name]);
            }

            
            listArr.Add(entity);
        }
    }
    catch ( ex)
    {
        throw ex;
    }
    finally
    {
        if (sdr != null) sdr.Close();
    }

    return listArr;
}
 

    1-3中第一行代码:TableInfo tableInfo = DbEntityUtils.GetTableInfo(entity,DbOperateType.SELECT);

将实体对象和操作类型传入DbEntityUtils.GetTableInfo方法中,下面是GetTableInfo代码1-4:

public static  GetTableInfo(object entity, dbOpType)
{
    
    bool breakForeach = false;
    
    string strPrimaryKey = string.Empty; 
    
     type = entity.GetType();             
    
     tableInfo = new ();
           
    tableInfo.TableName = GetTableName(type);
    
    
    [] properties = .GetProperties(type);
    foreach ( property in properties)
    {
        object propvalue = null;        string columnName = string.Empty;        string propName = columnName = property.Name;
 
  
        if(dbOpType != .SELECT)
            propvalue = .GetPropertyValue(entity, property);
        
                                        
        object[] propertyAttrs = property.GetCustomAttributes(false);
        for (int i = 0; i < propertyAttrs.Length; i++) 
        {
            object propertyAttr = propertyAttrs[i];
            
            
            if (.IsCaseColumn(propertyAttr, dbOpType))
                break;

            
            string tempName = GetColumnName(propertyAttr);
            
            
              columnName = tempName == string.Empty ? propName : tempName;                    
            
            if (propertyAttr is )
            {
                if (dbOpType == .INSERT)
                {                    
                    if (.IsNullOrEmpty(propvalue))
                    {

                                      //获取主键生成方式,存入tableInfo.Strategy属性中

                                      IdAttribute idAttr = propertyAttr as IdAttribute;
                                      tableInfo.Strategy = idAttr.Strategy;

 
 
  
 
  
                           strPrimaryKey = .GetPrimaryKey(propertyAttr);
                        if (!string.IsNullOrEmpty(strPrimaryKey))
                            propvalue = strPrimaryKey;
                    }
                }
                
                  tableInfo.Id.Key = columnName;
                tableInfo.Id.Value = propvalue;
                
                
                  tableInfo.PropToColumn.Put(propName, columnName);
                
                breakForeach = true
            }                        
        }
 
        
        if (breakForeach) { breakForeach = false; continue; }
        
        
         tableInfo.Columns.Put(columnName, propvalue);
        
        
         tableInfo.PropToColumn.Put(propName, columnName);
    }            

    return tableInfo;
}

    在代码1-3中用到了获取实体对象中自定义属性所配置的表名、列名代码分别为1-5:

public static string GetTableName( classType)
{                        
    string strTableName = string.Empty;
    string strEntityName = string.Empty;

    strEntityName = classType.FullName;

    object classAttr = classType.GetCustomAttributes(false)[0];
    if (classAttr is )
    {
         tableAttr = classAttr as ;
        strTableName = tableAttr.Name;
    }
    if (string.IsNullOrEmpty(strTableName))
    {
        throw new ("实体类:" + strEntityName + "的属性配置[Table(name=\"tablename\")]错误或未配置");
    }

    return strTableName;
}

    上面是获取表名,下面这段代码是获取列名,如下代码1-6:

public static string GetColumnName(object attribute)
{
    string columnName = string.Empty;
    if (attribute is )
    {
         columnAttr = attribute as ;
        columnName = columnAttr.Name;
    }
    if (attribute is )
    {
         idAttr = attribute as ;
        columnName = idAttr.Name;
    }

    return columnName;
}

1-3中第二行代码:String strSql = DbEntityUtils.GetFindByIdSql(tableInfo);
根据已经存入表信息的对象tableInfo来生成SQL语句,代码1-7:

public static  GetFindByIdSql( tableInfo)
{
     sbColumns = new ();

    if (tableInfo.Columns.ContainsKey(tableInfo.Id.Key))            
        tableInfo.Columns[tableInfo.Id.Key] = tableInfo.Id.Value;
    else
        tableInfo.Columns.Put(tableInfo.Id.Key, tableInfo.Id.Value);

    
    foreach (String key in tableInfo.Columns.Keys)
    {
        sbColumns.Append(key).Append(",");
    }

    sbColumns.Remove(sbColumns.ToString().Length - 1, 1);

    string strSql = "SELECT {0} FROM {1} WHERE {2} = " + .DbParmChar + "{2}";
    strSql = string.Format(strSql, sbColumns.ToString(), tableInfo.TableName, tableInfo.Id.Key);

    
    return strSql;
}

    下面是几个工具类代码,ReflectionUtils,根据反射获取或设置对象属性值、DynamicMethodCompiler动态方法编译,可提高反射的性能。

ReflectionUtilsusing System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;

namespace System.Orm.Common
{
    public class 
    {
        public static [] GetProperties( type)
        {
            return type.GetProperties(.Public | .Instance);
        }

        public static [] GetFields( type)
        {
            return type.GetFields(.Public | .Instance);
        }

        public static void SetPropertyValue(obj,  property, //创建Set委托
               setter = .CreateSetHandler(obj.GetType(),property);
                        
            //先获取该私有成员的数据类型
               type = property.PropertyType;

            //通过数据类型转换
              value = .ConvertForType(value, type);

            //将值设置到对象中
              setter(obj, value);            
        }       

        public static GetPropertyValue(obj,  property)
        {
            //创建Set委托
               getter = .CreateGetHandler(obj.GetType(), property);

            //获取属性值
              return getter(obj);
            
        }

        public static void SetFieldValue(obj,  field, value)
        {
            //创建Set委托
               setter = .CreateSetHandler(obj.GetType(), field);
            
            //先获取该私有成员的数据类型
               type = field.FieldType;

            //通过数据类型转换
              value = .ConvertForType(value, type);

            //将值设置到对象中
              setter(obj, value);
        }

        public static GetFieldValue(obj,  field)
        {
            //创建Set委托
               getter = .CreateGetHandler(obj.GetType(), field);

            //获取字段值
              return getter(obj);           
        }        
    }
}


DynamicMethodCompiler代码:

DynamicMethodCompilerusing System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Reflection.Emit;

namespace System.Orm.Common
{
    //定义GetHandler委托
     public delegate object (object source);
//定义SetHandler委托 public delegate void (object source, object value);
//定义InstantiateObjectHandler委托 public delegate object (); public sealed class { // DynamicMethodCompiler private DynamicMethodCompiler() { } // 创建InstantiateObject委托 internal static CreateInstantiateObjectHandler( type) { constructorInfo = type.GetConstructor(.Public | .NonPublic | .Instance, null, new [0], null); if (constructorInfo == null) { throw new (string.Format("The type {0} must declare an empty constructor (the constructor may be private, internal, protected, protected internal, or public).", type)); } dynamicMethod = new ("InstantiateObject", .Static | .Public, .Standard, typeof(object), null, type, true); generator = dynamicMethod.GetILGenerator(); generator.Emit(.Newobj, constructorInfo); generator.Emit(.Ret); return ()dynamicMethod.CreateDelegate (typeof()); } // 创建Get委托 internal static CreateGetHandler( type, propertyInfo) { getMethodInfo = propertyInfo.GetGetMethod(true); dynamicGet = CreateGetDynamicMethod(type); getGenerator = dynamicGet.GetILGenerator(); getGenerator.Emit(.Ldarg_0); getGenerator.Emit(.Call, getMethodInfo); BoxIfNeeded(getMethodInfo.ReturnType, getGenerator); getGenerator.Emit(.Ret); return ()dynamicGet.CreateDelegate(typeof()); } // 创建Get委托 internal static CreateGetHandler( type, fieldInfo) { dynamicGet = CreateGetDynamicMethod(type); getGenerator = dynamicGet.GetILGenerator(); getGenerator.Emit(.Ldarg_0); getGenerator.Emit(.Ldfld, fieldInfo); BoxIfNeeded(fieldInfo.FieldType, getGenerator); getGenerator.Emit(.Ret); return ()dynamicGet.CreateDelegate(typeof()); } // 创建Set委托 internal static CreateSetHandler( type, propertyInfo) { setMethodInfo = propertyInfo.GetSetMethod(true); dynamicSet = CreateSetDynamicMethod(type); setGenerator = dynamicSet.GetILGenerator(); setGenerator.Emit(.Ldarg_0); setGenerator.Emit(.Ldarg_1); UnboxIfNeeded(setMethodInfo.GetParameters()[0].ParameterType, setGenerator); setGenerator.Emit(.Call, setMethodInfo); setGenerator.Emit(.Ret); return ()dynamicSet.CreateDelegate(typeof()); } // 创建Set委托 internal static CreateSetHandler( type, fieldInfo) { dynamicSet = CreateSetDynamicMethod(type); setGenerator = dynamicSet.GetILGenerator(); setGenerator.Emit(.Ldarg_0); setGenerator.Emit(.Ldarg_1); UnboxIfNeeded(fieldInfo.FieldType, setGenerator); setGenerator.Emit(.Stfld, fieldInfo); setGenerator.Emit(.Ret); return ()dynamicSet.CreateDelegate(typeof()); } // 创建Get动态方法 private static CreateGetDynamicMethod( type) { return new ("DynamicGet", typeof(object), new [] { typeof(object) }, type, true); } // 创建Set动态方法 private static CreateSetDynamicMethod( type) { return new ("DynamicSet", typeof(void), new [] { typeof(object), typeof(object) }, type, true); } // BoxIfNeeded private static void BoxIfNeeded(type, ILGenerator generator) { if (type.IsValueType) { generator.Emit(.Box, type); } } // UnboxIfNeeded private static void UnboxIfNeeded(Type type, generator) { if (type.IsValueType) { generator.Emit(.Unbox_Any, type); } } } }

 

TypeUtils代码:

TypeUtilsusing System;
using System.Collections.Generic;
using System.Text;

namespace System.Orm.Common
{
    public class 
    {
        public static object ConvertForType(object value,type)
        {
            switch (type.FullName)
            {
                case "System.String":
                    value = value.ToString();
                    break;
                case "System.Boolean":
                    value = bool.Parse(value.ToString());
                    break;
                case "System.Int16":
                case "System.Int32":
                case "System.Int64":
                    value = int.Parse(value.ToString());
                    break;
                case "System.Double":
                    value = double.Parse(value.ToString());
                    break;
                case "System.Decimal":
                    value = new decimal(double.Parse(value.ToString()));
                    break;                                                             
            }

            return value;
        }
    }
}

 

    好了,FindById方法所需的代码和工具类代码都在上面,到此已经完成。

Technorati 标签: ORM

转载于:https://www.cnblogs.com/wangwei123/archive/2010/07/03/1770396.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值