这是我的代码:
#region Validate and prepare parameters
if (month > 12)
{
throw new ArgumentException("Value of 'month' could not be greater than 12.");
}
int yearEnd = year;
int monthEnd = 0;
if (month != 12)
{
monthEnd = month + 1;
}
else
{
monthEnd = 1;
yearEnd = year + 1;
}
#endregion
MyModelDataContext context = new MyModelDataContext();
string sql =
@"select SUM(ORDERQTY * MULTIPLIER) AS VOL_USD
from Executions with (nolock)
where TRANSACTTIME >= '{0}-{1}-01 00:00:00'
and TRANSACTTIME < '{2}-{3}-01 00:00:00'
and MTCONTEXT in (5,6)
and ORDERQTY > 0
AND SOURCE = 'INTMT'
and LEFT(SYMBOL, 3) = 'USD'";
decimal usd___Sum = context.ExecuteQuery<decimal>(sql, year, month, yearEnd, monthEnd).First();
我得到了例外:
从字符串转换日期和/或时间时转换失败。
当我调用 ExecuteQuery 方法时。年份的价值是2013年,月份的价值是9.我做错了什么?
提前致谢。
答案 0 :(得分:3)
您正在将字符串与日期进行比较,迫使数据库“猜测”正确的格式。您使用的格式不是ISO格式,因此数据库假定您使用与其排序规则匹配的格式。我敢打赌你使用LATIN1或类似的东西。
不是传递整数,而是将它们转换为字符串,例如在TRANSACTTIME >= '{0}-{1}-01 00:00:00'
中,只需传递日期:
var startDate=new DateTime(year,month,1);
var endDate=new DateTime(yearEnd,monthEnd,1);
string sql =
@"select SUM(ORDERQTY * MULTIPLIER) AS VOL_USD
from Executions with (nolock)
where TRANSACTTIME >= {0}
and TRANSACTTIME < {1}
and MTCONTEXT in (5,6)
and ORDERQTY > 0
AND SOURCE = 'INTMT'
and LEFT(SYMBOL, 3) = 'USD'";
decimal usd___Sum = context.ExecuteQuery<decimal>(sql, startDate,endDate).First();
<强>更新强>
正如Ovidiu所说,参数替换在字符串内部不起作用,因此即使我们提供@ p0,@ p1参数的值,'@ p0- @ p1-01'也将保持不变。我们需要通过连接每个部分来创建字符串之外的日期。
在SQL Server 2012中,我们有DATETIMEFROMPARTS的另一个选项。我们可以从其各个部分创建日期,例如:
string sql =
@"select SUM(ORDERQTY * MULTIPLIER) AS VOL_USD
from Executions with (nolock)
where TRANSACTTIME >= DATETIMEFROMPARTS({0},{1},1,0,0,0,0)
..."
虽然通过实际日期仍然是可取的
答案 1 :(得分:1)
问题是context.ExecuteQuery
将查询发送到数据库的方式。虽然它使用{0}之类的参数,类似于string.Format
,但它实际上并不用字符串值替换这些参数,而是将它们作为参数发送给DB。这有点令人困惑。
如果您打开SQL事件探查器,您将看到您的查询转换为类似
的内容exec sp_executesql
N'select SUM(ORDERQTY * MULTIPLIER) AS VOL_USD
from Executions with (nolock)
where TRANSACTTIME >= ''@p0-@p1-01 00:00:00''
and TRANSACTTIME < ''@p2-@p3-01 00:00:00'''
,N'@p0 int,@p1 int,@p2 int,@p3 int'
,@p0=2013,@p1=9,@p2=2013,@p3=10
这将在SQL中引发异常,因为参数@p0
出现在单引号内,因此被解释为字符串"@p0"
,而不是替换为2013
的实际值。因此,您最终会使用'2013-09-01 00:00:00'
'@p0-@p1-01 00:00:00'
发送DateTime
个对象而非字符串将是更好的解决方案
where TRANSACTTIME >= {0} and and TRANSACTTIME < {1}
...
context.ExecuteQuery<decimal>(sql, new DateTime(year, month, 1), new DateTime(yearEnd, monthEnd, 1))
但是如果你仍然想要保持当前的构造,你必须记住,参数{0}
在SQL中变成参数@p0
并使用类似的东西
where TRANSACTTIME >= convert(datetime, {0} + '-' + {1} + '-01 00:00:00')
and TRANSACTTIME < convert(datetime, {2} + '-' + {3} + '-01 00:00:00')
...
context.ExecuteQuery<decimal>(sql, year.ToString(), month.ToString(), yearEnd.ToString(), monthEnd.ToString())