我正在 SQL 过程之上创建“通用”包装器,我可以解析所有必需参数的名称和 sqltypes,但是有什么方法可以获取它的“底层”.NET 类型吗?
我的目标是做这样的事情:
SqlParameter param;
object value;
object correctParam = param.GetNETType().GetMethod("Parse",
new Type[] { typeof(string) }).Invoke(value.ToString());
param.Value = correctParam;
我需要的是 GetNETType。 我知道它可以写成 param.SqlDbType 内部的开关,但这是更短的方式,更短的注释代码意味着更少的维护:)
最佳答案
不幸的是,据我所知,此映射并未在 .NET Framework 内的代码中公开。为此,我之前查看了 .NET Framework 引用源,发现在 .NET 代码中有很多很长的每种类型的 switch 语句,就像您试图避免的那些一样,但它们似乎都没有暴露在外。
如果您真的只是想从 SqlTypes 映射到最常见的 .NET 类型,我认为您最好的选择是简单地转换映射表 in the MSDN docs成代码。请注意,MSDN 上的表格(至少)有两个错误:#1:没有名为“DateTime2”的 .NET 类型(我使用的是 DateTime),也没有名为“Xml”的类型(我使用的是 SqlXml)。
无论如何,这是我一直在使用的映射——使用字典而不是开关以便于访问而无需单独的方法。
public static Dictionary<SqlDbType, Type> TypeMap = new Dictionary<SqlDbType, Type>
{
{ SqlDbType.BigInt, typeof(Int64) },
{ SqlDbType.Binary, typeof(Byte[]) },
{ SqlDbType.Bit, typeof(Boolean) },
{ SqlDbType.Char, typeof(String) },
{ SqlDbType.Date, typeof(DateTime) },
{ SqlDbType.DateTime, typeof(DateTime) },
{ SqlDbType.DateTime2, typeof(DateTime) },
{ SqlDbType.DateTimeOffset, typeof(DateTimeOffset) },
{ SqlDbType.Decimal, typeof(Decimal) },
{ SqlDbType.Float, typeof(Double) },
{ SqlDbType.Int, typeof(Int32) },
{ SqlDbType.Money, typeof(Decimal) },
{ SqlDbType.NChar, typeof(String) },
{ SqlDbType.NText, typeof(String) },
{ SqlDbType.NVarChar, typeof(String) },
{ SqlDbType.Real, typeof(Single) },
{ SqlDbType.SmallInt, typeof(Int16) },
{ SqlDbType.SmallMoney, typeof(Decimal) },
{ SqlDbType.Structured, typeof(Object) }, // might not be best mapping...
{ SqlDbType.Text, typeof(String) },
{ SqlDbType.Time, typeof(TimeSpan) },
{ SqlDbType.Timestamp, typeof(Byte[]) },
{ SqlDbType.TinyInt, typeof(Byte) },
{ SqlDbType.Udt, typeof(Object) }, // might not be best mapping...
{ SqlDbType.UniqueIdentifier, typeof(Guid) },
{ SqlDbType.VarBinary, typeof(Byte[]) },
{ SqlDbType.VarChar, typeof(String) },
{ SqlDbType.Variant, typeof(Object) },
{ SqlDbType.Xml, typeof(SqlXml) },
};
请注意,您需要注意的一件事是大小/精度——某些 SQL 类型(例如 varchar)有大小限制,而 .NET 类型(例如 string) 不要。因此,仅仅知道最有可能的 .NET 类型还不够......如果您使用它来驱动验证规则,您还需要能够防止用户输入无效(例如太大) 值通过更多地了解参数,如精度。请注意,如果您查看 SqlClient 源代码,它们会使用特殊代码来处理一些情况,例如根据相应的 SQL 精度设置 Decimal 类型的精度。
请注意,如果您需要 .NET 类型的唯一原因是能够将数据填充到存储的 proc 参数中,您可能想尝试简单地对所有 .NET 值使用 ToString(),将字符串填充到SqlParameter 的 Value 属性,并查看框架是否会为您进行转换/解析。例如,对于 XML 或 Date 参数,您可以改为发送字符串。
此外,由于存在一个已知的(和小的)类型列表,而不是使用反射来查找每种类型的 Parse() 方法,您可以通过对每种类型使用强类型解析代码来获得更好的性能,例如代码以下。 (请注意,几种类型(例如 SqlDbType.Udt)不一定具有明显的解析器方法——您需要弄清楚要如何处理它们。)
public static Dictionary<SqlDbType, Func<string, object>> TypeMapper = new Dictionary<SqlDbType, Func<string, object>>
{
{ SqlDbType.BigInt, s => Int64.Parse(s)},
{ SqlDbType.Binary, s => null }, // TODO: what parser?
{ SqlDbType.Bit, s => Boolean.Parse(s) },
{ SqlDbType.Char, s => s },
{ SqlDbType.Date, s => DateTime.Parse(s) },
{ SqlDbType.DateTime, s => DateTime.Parse(s) },
{ SqlDbType.DateTime2, s => DateTime.Parse(s) },
{ SqlDbType.DateTimeOffset, s => DateTimeOffset.Parse(s) },
{ SqlDbType.Decimal, s => Decimal.Parse(s) },
{ SqlDbType.Float, s => Double.Parse(s) },
{ SqlDbType.Int, s => Int32.Parse(s) },
{ SqlDbType.Money, s => Decimal.Parse(s) },
{ SqlDbType.NChar, s => s },
{ SqlDbType.NText, s => s },
{ SqlDbType.NVarChar, s => s },
{ SqlDbType.Real, s => Single.Parse(s) },
{ SqlDbType.SmallInt, s => Int16.Parse(s) },
{ SqlDbType.SmallMoney, s => Decimal.Parse(s) },
{ SqlDbType.Structured, s => null }, // TODO: what parser?
{ SqlDbType.Text, s => s },
{ SqlDbType.Time, s => TimeSpan.Parse(s) },
{ SqlDbType.Timestamp, s => null }, // TODO: what parser?
{ SqlDbType.TinyInt, s => Byte.Parse(s) },
{ SqlDbType.Udt, s => null }, // consider exception instead
{ SqlDbType.UniqueIdentifier, s => new Guid(s) },
{ SqlDbType.VarBinary, s => null }, // TODO: what parser?
{ SqlDbType.VarChar, s => s },
{ SqlDbType.Variant, s => null }, // TODO: what parser?
{ SqlDbType.Xml, s => s },
};
上面使用的代码非常简单,例如:
string valueToSet = "1234";
SqlParameter p = new SqlParameter();
p.SqlDbType = System.Data.SqlDbType.Int;
p.Value = TypeMapper[p.SqlDbType](valueToSet);
关于c# - 如何在 SQL 中检索给定 StoredProcedure 参数的 .NET 类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1594711/
出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits
作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende
我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere
是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou
我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"
我可以得到Infinity和NaNn=9.0/0#=>Infinityn.class#=>Floatm=0/0.0#=>NaNm.class#=>Float但是当我想直接访问Infinity或NaN时:Infinity#=>uninitializedconstantInfinity(NameError)NaN#=>uninitializedconstantNaN(NameError)什么是Infinity和NaN?它们是对象、关键字还是其他东西? 最佳答案 您看到打印为Infinity和NaN的只是Float类的两个特殊实例的字符串