简要说明:
我们有一个接受参数的C#方法。
在该方法内部我们需要添加Sql参数(根据方法参数)。
它看起来像这样: http://i.stack.imgur.com/QP1y2.jpg(放大)
请注意
我可以编写一个包含所有方法参数的类。但是,我将不得不为每个SP创建一个类容器(我们有很多)。
好的,继续。
我在想:“为什么我应该insert each param manually - 如果我已经拥有:name
,type
,value
in方法参数?我不想这样做,也许反思会为我做这件事“(暂时离开int <->DbType.Int32
的转换)
但我遇到了一个问题。 可能使用反射读取值。
然而,我确实设法通过黑客反射来读取值。
1)我做了这个例子:(模拟真实场景)
public static void MyMethod(int AddressId, string countryId, DateTime dt) //these are the arguments which need to be attached later
{
MethodBase mi = MethodInfo.GetCurrentMethod();
var hack = new {AddressId, countryId, dt}; //this is the HACK
var lstArguments = mi.GetParameters() //get the parameter name and types
.Select(p => new {
name = p.Name , type=p.GetType().Name
}).ToList();
List < dynamic > lstParamValues= new List < dynamic > ();
foreach(PropertyInfo pi in hack.GetType().GetProperties()) //get the value(!!!) of each param
{
lstParamValues.Add(pi.GetValue(hack, null));
}
dynamic dyn= myDBInstance; // get dynamic reference to the DB class instance (
for(int i = 0; i < lstArguments .Count; i++) //dynamically Invoke the method with param name+value.
{
dyn.AddInParameter(lstArguments [i].name, ((lstParamValues[i] is int) ? DbType.Int32 : DbType.String), lstParamValues[i]);
}
}
还有数据库类(模拟 AddInParameter
以查看我是否获得了值)
class myDB
{
public void AddInParameter(string name, DbType dbt, object val)
{
Console.WriteLine("name=" + name + " " + "DbType=" + dbt + " " + "object val=" + val);
}
}
它正在运作:
我用以下方法执行了该方法:
MyMethod(1, "2", DateTime.Now);
输出结果为:
name=AddressId DbType=Int32 object val=1
name=countryId DbType=String object val=2
name=dt DbType=String object val=05/02/2013 19:09:32
一切都很好。
C#问题
我怎样才能克服这个黑客攻击:
var hack = new {AddressId, countryId, dt}; // the method arguments names
在我的样本中,我写了硬编码。
反射方法GetValue
仅适用于此行。
我可以做些什么来在运行时添加方法参数名称作为属性,所以我将能够做到:
foreach(PropertyInfo pi in SOMETHING.GetType().GetProperties())
{
}
请将此问题视为c#问题,而不是ORM问题。
另外,如果你想玩正在运行的示例代码(只需粘贴在控制台项目中):http://jsbin.com/azicut/1/edit
答案 0 :(得分:0)
这能提供一些缓解吗?
这样做一次(在DAL ctor中):
SqlParameter sqlCmdFTSindexWordOnceParam = sqlCmdFTSindexWordOnce.Parameters.Add("@sID", SqlDbType.Int);
sqlCmdFTSindexWordOnceParam.Direction = ParameterDirection.Input;
SqlParameter sqlCmdFTSindexWordOnceParam2 = sqlCmdFTSindexWordOnce.Parameters.Add("@sIDpar", SqlDbType.Int);
sqlCmdFTSindexWordOnceParam2.Direction = ParameterDirection.Input;
然后在电话中:
sqlCmdFTSindexWordOnceParam.Value = wdc.sID;
sqlCmdFTSindexWordOnceParam2.Value = wdc.sIDpar;
sqlCmdFTSindexWordOnce.BeginExecuteNonQuery(callbackFTSindexWordOnce, sqlCmdFTSindexWordOnce);
比为每个调用添加参数更好的性能。
答案 1 :(得分:0)
AddWithValue
至少可以避免编写类型名称。
command.Parameters.AddWithValue("@demographics", demoXml);
但是你真的不能把那么多参数传递给一个函数。一个简单的DTO类可以使您的代码更具可读性。如果我没弄错的话,你看起来像pyhton的locals
(Need something like locals in python),它给你作为键值对的局部变量函数,据我所知你不能在c#中这样做。
或者你很简单,不传递你可以传递Dictionary<string,object>
的所有变量并将关键值添加到SqlParameter
答案 2 :(得分:-3)
我不熟悉c#和.net的工作方式,但如果这是java,我会说:
将当前参数存储到arraylist或map
你可以有3个arraylists,一个用于进入addInParameters方法调用的每个参数,或者包含所有值的map(类型参数需要像现在一样重复)< / p>
使用数组列表作为插入/更新方法中的唯一参数 使用for循环以便AddInParameter调用只写一次,参数类似于(array1 [0],array2 [0],array3 [0])而不是实际值。
在php中你可以使用关联数组,.net是否有关联数组?