手把手教你写ORM(八)
最后我们来解决点遗留问题
首先是读取Attribute的问题
大致的方法就是这样子。
还有就是如何通过“NChar”等字符串获取System.Data.SqlDBType这个枚举的类型的值
其实也不难,
SqlDbType ptype = (SqlDbType)System.Enum.Parse(typeof(SqlDbType), "VarChar");
这样子就可以了
最后我们实现一个数据库操作组件就可以把上面内容组合起来了,下面贴的代码是我自己写了个很粗糙的例子上的
细节上和之前几篇可能有点出入,不过思想是一致的
关于事务的问题我们以后再说
最后附上我穷一晚上功夫写的粗糙的例子作文本系列的结束
希望这两天来写下的问题能够带领菜菜鸟们走进ORM的一些看似神秘的实现细节,有些是我借鉴了其他的源码,有些是完全自己杜撰的,不管怎么说那个粗糙的例子运行还算良好,不过之前没有好好精细设计一下,有点凌乱的感觉。
http://www.81831.com/FileUpload/Xbase.rar 这是那个粗糙的例子
因为公司的测试服务器老挂,我在这里也放一个 https://files.cnblogs.com/Alexander-Lee/Xbase.rar
首先是读取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;
}
}
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<string, object> paramlist = new SortedList<string, object>();
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<string, object> paramdata = new SortedList<string, object>();
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;
}
}
}
}
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<string, object> paramlist = new SortedList<string, object>();
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<string, object> paramdata = new SortedList<string, object>();
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