手把手教你写ORM(八)

最后我们来解决点遗留问题
首先是读取Attribute的问题
Type tp = target.GetType();
PropertyInfo pp 
= tp.GetProperty(s);
foreach (object o in pp.GetCustomAttributes(false))
{
    
if (o.GetType().Equals(typeof(ParamAttribute)))
    
{
        ParamAttribute p 
= (ParamAttribute)o;
        
//这里P就是Attribute的对象啦
        break;
    }

}

大致的方法就是这样子。

还有就是如何通过“NChar”等字符串获取System.Data.SqlDBType这个枚举的类型的值
其实也不难,
SqlDbType ptype = (SqlDbType)System.Enum.Parse(typeof(SqlDbType), "VarChar");
这样子就可以了

最后我们实现一个数据库操作组件就可以把上面内容组合起来了,下面贴的代码是我自己写了个很粗糙的例子上的
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.Collections;
using System.Reflection;
using Alexander.Xbase.ClassConfig;
using Alexander.Xbase.Xcache;
using Alexander.Xbase.Xresource;
using Alexander.Xbase.Interface;

namespace Alexander.Xbase.SqlExec
{
    
public class Exec: Alexander.Xbase.Interface.IQueriable
    
{

        
private string ConnectionString;
        
private SqlConnection conn;
        
private SqlTransaction tran;
        
private bool TransOpen;
        
private string configpath;
        
IQueriable 成员

        
private string DoPageSql(String command, int pageid, int pagesize, string sort, string direct)
        
{
            
int All = pagesize * pageid;
            StringBuilder PageSql 
= new StringBuilder("SELECT * FROM (SELECT TOP #PageSize * FROM (SELECT TOP #ALLCount * FROM (#SelectCommand) AS t0 ORDER BY #SortField DESC) AS t1 ORDER BY #SortField ASC) AS t2 ORDER BY #SortField " + direct);
            PageSql.Replace(
"#PageSize", pagesize.ToString());
            PageSql.Replace(
"#ALLCount", All.ToString());
            PageSql.Replace(
"#SelectCommand", command);
            PageSql.Replace(
"#SortField", sort);
            
return PageSql.ToString();
        }


        
private string DoCountSql(string command)
        
{
            
string work = command.ToLower();
            
int startindex = work.IndexOf("select"+ 7;
            
int endindex = work.LastIndexOf("from"- 1;
            work 
= work.Remove(startindex, endindex - startindex);
            work 
= work.Insert(startindex, "count(*)");
            
return work;
        }


        
private object Count(string action,string sql, object target)
        
{
            
object rs = new object();
            ConfigStruct config 
= new ConfigStruct(new Resource(configpath + target.GetType().Name+".xml").Data);
            
string execsql = MakeExecuteSql(sql);
            
string storedsql = MakeValueSql(sql, target);
            
string sKey = target.GetType().Name + ":" + storedsql;
            
if (config.IsCache(action))
            
{
                
if (IsInCache(sKey, rs))
                
{
                    
return ObjCache.GetObject[sKey];
                }

            }

            SqlCommand comm 
= new SqlCommand(execsql, conn);
            PrepareCommand(comm, sql, target);
            rs 
= comm.ExecuteScalar();
            
if (config.IsCache(action))
            
{
                ObjCache.Insert(sKey, rs);
            }

            
return rs;
        }


        
private string MakeExecuteSql(string RawSql)
        
{
            
return RawSql.Replace("#""@");
        }

        
private string MakeValueSql(string RawSql,object target)
        
{
            SortedList
<stringobject> paramlist = new SortedList<stringobject>();
            
string RS=RawSql;
            ConfigStruct.GetParam(RawSql, paramlist, target);
            
foreach (string Key in paramlist.Keys)
            
{
                RS 
= RS.Replace("#" + Key, paramlist[Key].ToString());
            }

            
return RS;
        }


        
private object FillObject(SqlDataReader rd,Type tp)
        
{
            
string Key=string.Empty;
            
object rs = System.Activator.CreateInstance(tp);
            
foreach (PropertyInfo pp in tp.GetProperties())
            
{

                
foreach (object o in pp.GetCustomAttributes(false))
                
{
                    
if (o.GetType().Equals(typeof(ParamAttribute)))
                    
{
                        ParamAttribute p 
= (ParamAttribute)o;

                        
if (p.Srccolumn != null)
                        
{
                            Key 
= p.Srccolumn;
                        }

                        
else
                        
{
                            Key 
= pp.Name;
                        }

                        
if (rd[Key] != null)
                        
{
                            
//rs = rd[Key];
                            pp.SetValue(rs, rd[Key], new object[] { });
                        }

                        
break;
                    }

                }

            }

            
return rs;
        }


        
private void PrepareCommand(SqlCommand cmd, string sql, object tar)
        
{
            SortedList
<stringobject> paramdata = new SortedList<stringobject>();
            SortedList
<string, ParamAttribute> paramstruct = new SortedList<string, ParamAttribute>();
            ConfigStruct.GetParam(sql, paramdata, tar);
            ConfigStruct.GetParamType(sql, paramstruct, tar);
            
for (int i = 0; i < paramstruct.Count; i++)
            
{
                SqlDbType ptype 
= (SqlDbType)System.Enum.Parse(typeof(SqlDbType), paramstruct.Values[i].ParameterType);
                cmd.Parameters.Add(
"@" + paramdata.Keys[i], ptype, paramstruct.Values[i].ParameterLength).Value = paramdata.Values[i];
            }

            
if (this.TransOpen)
            
{
                cmd.Transaction 
= this.tran;
            }

        }

        
private bool IsInCache(string action, object rs)
        
{
            
if (ObjCache.GetObject.TryGetValue(action, out rs))
            
{
                
return true;
            }

            
else
            
{
                
return false;
            }

        }

    }

}



细节上和之前几篇可能有点出入,不过思想是一致的

关于事务的问题我们以后再说
最后附上我穷一晚上功夫写的粗糙的例子作文本系列的结束
希望这两天来写下的问题能够带领菜菜鸟们走进ORM的一些看似神秘的实现细节,有些是我借鉴了其他的源码,有些是完全自己杜撰的,不管怎么说那个粗糙的例子运行还算良好,不过之前没有好好精细设计一下,有点凌乱的感觉。

http://www.81831.com/FileUpload/Xbase.rar 这是那个粗糙的例子
因为公司的测试服务器老挂,我在这里也放一个 https://files.cnblogs.com/Alexander-Lee/Xbase.rar

posted on 2007-01-25 11:26  亚历山大同志  阅读(3933)  评论(7编辑  收藏  举报

导航