[英]How to pass Datetime parameter as string to web api controller (httpPut) PutAysnc
[英]Pass datetime parameter in Web API?
我想问Web API中如何传递datetime参数,如何在可选日期中传递datetime参数。 我想在URL中搜索可以不带时间的可选日期如:
localhost:IP/api/values?date=2020-01-01
预期成绩:
<ArrayOfTest xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Test>
<UserId>341</UserId>
<Name>Emily</Name>
<Mobile>386754298</Mobile>
<Age>24</Age>
<Date>2021-11-06T16:04:00</Date>
</Test>
<Test>
<UserId>2555</UserId>
<Name>Peter</Name>
<Mobile>48295729</Mobile>
<Age>45</Age>
<Date>2020-10-12T20:35:00</Date>
</Test>
它可以在2020-01-01之后找到日期。 一些值是来自 SQL 服务器数据库的 null,所以我使用dbnull
来确保代码有效并且我没有使用实体框架连接数据库,我尝试只在 get 方法中传递 datetime 参数,但它不能正常工作. 是否可以像这样传递数据时间参数?
Class 代码:
public class TestClass
{
public string UserId { get; set; }
public string Name { get; set; }
public string Mobile { get; set; }
public int Age { get; set; }
public DateTime? Date { get; set; }
}
controller 代码:
public IHttpActionResult Get(DateTime date)
{
List<UserClass> Test = new List<UserClass>();
string mainconn = ConfigurationManager.ConnectionStrings["myconn"].ConnectionString;
SqlConnection sqlconn = new SqlConnection(mainconn);
string sqlquery = "SELECT UserID, Name, Mobile, Age, Date From tbluser where Date="+date+";
sqlconn.Open();
SqlCommand sqlcomm = new SqlCommand(sqlquery, sqlconn);
SqlDataReader reader = sqlcomm.ExecuteReader();
while (reader.Read())
{
Test.Add(new UserClass()
{
UserId = reader.GetValue.ToString(0),
Name = reader.GetValue.ToString(1),
Mobile = reader.GetValue.ToString(2),
Access = Convert.ToInt32(reader.GetValue(3)),
Date = (reader.GetValue(4) != DBNull.Value) ? Convert.ToDateTime(reader.GetValue(4)) : (DateTime?)null
});
}
return Ok(Test);
}
你不应该添加这样的字符串
SELECT UserID, Name, Mobile, Age, Date From tbluser where Date="+date+"
这可能会导致SQL 注入。 相反,请使用日期类型为https://docs.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlcommand.parameters?view=dotnet-plat-ext-6.0 的SQL 参数遵循本文档
这是示例:
string sqlquery = "SELECT UserID, Name, Mobile, Age, Date From tbluser where Date= @YourDate";
SqlCommand sqlcomm = new SqlCommand(sqlquery, sqlconn);
sqlcomm.Parameters.Add("@YourDate", SqlDbType.Date);
sqlcomm.Parameters["@YourDate"].Value = date;
使用字符串连接构建查询时,建议您对日期使用 ISO 日期格式:
在 C# 中,我们可以使用u
格式说明符来获取 SQL 的 ISO 日期,但它会在值后面附加一个Z
,以下是在字符串中使用它的简单方法:
date.ToString("u").TrimEnd('Z');
这相当于:
date.ToString("yyyy-MM-dd HH:mm:ss");
但是现在我们有一个问题,传入的日期参数是代表一整天,还是代表一个特定的时间点(为了这个查询的目的)? 您的要求是我们只想指定日期,不指定时间,因为我们可以使用这种格式:
date.ToString("yyyy-MM-dd")
现在我们遇到了一个新问题,在 SQL 中,如果您的数据包含时间值,那么您需要将数据截断为仅日期部分,以获取所提供日期的所有值。
所以现在您的查询如下所示:
string sqlquery = "SELECT UserID, Name, Mobile, Age, Date From tbluser where Cast([Date] as Date) = '"+date.ToString("yyyy-MM-dd")+"'";
在where
子句中使用 function 使得这是一个非 SARGABLE 查询,这对于数据库来说很难优化,通常通过使用BETWEEN
并传入date
和第二天的日期值可以获得更好的性能:
string sqlquery = "SELECT UserID, Name, Mobile, Age, Date From tbluser where [Date] BETWEEN '"+date.ToString("yyyy-MM-dd")+"' AND '"+date.AddDays(1). ToString("yyyy-MM-dd")+"'";
但是现在这个查询有点乱,我们应该使用参数来传递值,这样我们就不需要知道 ISO 日期和格式,ADO.Net 运行时会为我们处理。
参数化查询提供其他好处,例如 SQL 通过输入清理和其他处理优化防止注入
让我们更改查询以使用参数:
string sqlquery = "SELECT UserID, Name, Mobile, Age, Date From tbluser where Date BETWEEN @fromDate AND @toDate";
然后你需要将日期作为参数传递给SqlCommand
,
请注意,我们在
DateTime
object 上使用.ToDate()
方法来修剪用户可能提供的时间部分。
SqlCommand sqlcomm = new SqlCommand(sqlquery, sqlconn);
sqlcomm.Parameters.Add("@fromDate ", SqlDbType.Date);
sqlcomm.Parameters["@fromDate "].Value = date.Date;
sqlcomm.Parameters.Add("@toDate ", SqlDbType.Date);
sqlcomm.Parameters["@toDate "].Value = date.AddDays(1).Date;
这是比较字符串连接 SQL 与参数化查询的好帖子: C#: SQL
更新请参阅此小提琴进行现场演示: https://dotnetfiddle.net/8zLLrR
Because your controller is pre-sanitizing the input and constraining it to a DateTime
typed value, SQL Injection is not likely to be an issue in this specific example, however the string-concatenation approach to build your query is generally a red flag in Web API因为这是您的代码最容易受到外部输入影响的地方。
SQL 服务器有一个优化,它在重新执行查询时尝试重新使用执行计划。 当您第一次运行查询时,您会在 SSMS 中注意到,如果您重新执行相同的查询,它几乎总是比第二次慢。 那是因为它有一个存储执行计划的内部表,而您提交的SQL
是该索引的主键。
当日期过滤器更改时,如果您使用字符串连接,这会导致不同的SQL
,因此数据库引擎更难查找现有的查询执行计划,并且在许多情况下它会生成一个新的查询执行计划。 当我们使用参数时,实际的SQL
查询每次都是相同的,因此优化器可以简单地查找任何以前保存的执行计划。
SQL 服务器的更高版本有额外的优化,可以自动参数化执行计划索引的查询表达式,但这不是 100%,也不是懒惰的开发人员的借口;)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.