您的位置:首页 > 其它

(转)用DynamicMethod提升ORM系统转换业务数据的性能

2007-08-08 13:50 405 查看
原文

用DynamicMethod提升ORM系统转换业务数据的性能

在上一篇文章《把Sql数据转换为业务数据的几种方法》中提到了ORM系统把Sql数据转换为业务数据的几种方法,但这些方法都不是最佳的方法,后有白菜园等朋友提出用DynamicMethod,发现该方法确实是一个理想的解决方案:

1、在设计的时候业务实体类的定义非常简洁;

2、在运行的时候效率比较高,在某些情况下,甚至与硬编码的效率相等。

3、解偶了数据转换类和业务实体类之间的关系,可以对任意的业务实体类进行转换而不用对他们进行修改。

经过简单测试,发现用DynamicMethod的时间大约是硬编码的1~1.2倍,而用反射所花的时间大约是硬编码和DynamicMethod的4~6.5倍。现与大家分享代码,期待能够找到更加好的方法。

业务实体类User,对应着数据库的Users表:

public class User

{

string _UserID;

public string UserID

{

get { return _UserID; }

set { _UserID = value; }

}

string _UserName;

public string UserName

{

get { return _UserName; }

set { _UserName = value; }

}

string _Email;

public string Email

{

get { return _Email; }

set { _Email = value; }

}

string _Pwd;

public string Pwd

{

get { return _Pwd; }

set { _Pwd = value; }

}

}

用于执行DynamicMethod的委托:

public delegate T FillBusinessObject<T>(IDataReader AReader);

创建DynamicMethod:

public class BusinessSetter

{

static string[] GetFields(string tableName)

{

return new String[] { "UserID", "UserName", "Email", "Pwd" };

}

public static FillBusinessObject<T> GetFillMethod<T>(string tableName) where T : new()

{

Type AType = typeof(T);

Type[] methodArgs ={ typeof(IDataReader) };

DynamicMethod AFillMethod = new DynamicMethod("", AType, methodArgs, AType);

ILGenerator il = AFillMethod.GetILGenerator();

MethodInfo DataReaderGet = typeof(SqlDataReader).GetMethod("get_Item", new Type[] { typeof(string) });

ConstructorInfo createInfo = AType.GetConstructor(new Type[0]);

il.DeclareLocal(AType);

il.Emit(OpCodes.Newobj, createInfo);

il.Emit(OpCodes.Stloc_0);

string[] Fields = GetFields(tableName);

foreach (string AFieldName in Fields)

{

PropertyInfo AProp = AType.GetProperty(AFieldName);

MethodInfo PropSetMethod = AProp.GetSetMethod();

il.Emit(OpCodes.Ldloc_0);

il.Emit(OpCodes.Ldarg_0);

il.Emit(OpCodes.Ldstr, AFieldName);

il.Emit(OpCodes.Callvirt, DataReaderGet);

il.Emit(OpCodes.Isinst, AProp.PropertyType);

il.Emit(OpCodes.Callvirt, PropSetMethod);

}

il.Emit(OpCodes.Ldloc_0);

il.Emit(OpCodes.Ret);

return (FillBusinessObject<T>)AFillMethod.CreateDelegate(typeof(FillBusinessObject<T>));

}

}

测试:

public class Test

{

public static void Main()

{

FillBusinessObject<User> AMethod = BusinessSetter.GetFillMethod<User>("Users");

string Sql = "select UserID,UserName,Pwd,Email from Users";

SqlConnection con = new SqlConnection(System.Configuration.ConfigurationManager.AppSettings["DbCon"]);

SqlCommand cmd = new SqlCommand(Sql, con);

con.Open();

for (int i = 0; i < 5; i++)

{

//DynamicMethod

Console.WriteLine("{0}th time:",i+1);

SqlDataReader reader = cmd.ExecuteReader();

long dynamic = 0;

long start = DateTime.Now.Ticks;

while (reader.Read())

{

User AUser=AMethod(reader);

}

long end = DateTime.Now.Ticks;

reader.Close();

dynamic = end - start;

Console.WriteLine("dynamic:{0}", dynamic);

// Hardcode

reader = cmd.ExecuteReader();

start = DateTime.Now.Ticks;

while (reader.Read())

{

User AUser = new User();

AUser.UserName = reader["UserName"] as string;

AUser.Email = reader["Email"] as string;

AUser.UserID = reader["UserID"] as string;

AUser.Pwd = reader["Pwd"] as string;

}

end = DateTime.Now.Ticks;

reader.Close();

long hardcode = end - start;

Console.WriteLine("hardcode:{0}", hardcode);

//Reflect

reader = cmd.ExecuteReader();

Type UserType=typeof(User);

PropertyInfo[] UserInfos ={

UserType.GetProperty("UserID"),

UserType.GetProperty("UserName"),

UserType.GetProperty("Pwd"),

UserType.GetProperty("Email")};

start = DateTime.Now.Ticks;

while (reader.Read())

{

User AUser = new User();

foreach (PropertyInfo info in UserInfos)

info.SetValue(AUser, reader[info.Name], null);

}

end = DateTime.Now.Ticks;

reader.Close();

long reflect = end - start;

Console.WriteLine("reflect:{0}", reflect);

Console.WriteLine("dynamic/hardcode={0}", (float)dynamic / (float)hardcode);

Console.WriteLine("reflect/hardcode={0}", (float)reflect / (float)hardcode);

Console.WriteLine("reflect/dynamic={0}", (float)reflect / (float)dynamic);

Console.WriteLine();

Thread.Sleep(50);

}

con.Close();

Console.Read();

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: