Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 其中位于(ID数组)_C#_Sql Server_Tsql_Ado.net_Sqlparameter - Fatal编程技术网

C# 其中位于(ID数组)

C# 其中位于(ID数组),c#,sql-server,tsql,ado.net,sqlparameter,C#,Sql Server,Tsql,Ado.net,Sqlparameter,我有一个webservice,它被传递了一个int数组。 我希望按如下方式执行select语句,但不断出现错误。是否需要将数组更改为字符串 [WebMethod] public MiniEvent[] getAdminEvents(int buildingID, DateTime startDate) { command.CommandText = @"SELECT id, startDateTime, endDateTim

我有一个webservice,它被传递了一个int数组。 我希望按如下方式执行select语句,但不断出现错误。是否需要将数组更改为字符串

[WebMethod]
public MiniEvent[] getAdminEvents(int buildingID, DateTime startDate)
{    
    command.CommandText = @"SELECT id,
                            startDateTime, endDateTime From
                            tb_bookings WHERE buildingID IN
                            (@buildingIDs) AND startDateTime <=
                            @fromDate";

    SqlParameter buildID = new SqlParameter("@buildingIDs", buildingIDs);
}
[WebMethod]
公共迷你事件[]getAdminEvents(int buildingID,DateTime startDate)
{    
command.CommandText=@“选择id,
startDateTime,endDateTime From
buildingID所在的tb\U预订
(@buildingIDs)和startDateTime访问,了解如何执行此操作。

您(很遗憾)无法执行此操作。Sql参数只能是单个值,因此您必须执行以下操作:

WHERE buildingID IN (@buildingID1, @buildingID2, @buildingID3...)
当然,这需要您知道有多少个建筑ID,或者动态构造查询

作为解决方法*,我已完成以下工作:

WHERE buildingID IN (@buildingID)

command.CommandText = command.CommandText.Replace(
  "@buildingID", 
  string.Join(buildingIDs.Select(b => b.ToString()), ",")
);
它将用数字替换语句的文本,结果如下:

WHERE buildingID IN (1,2,3,4)
  • 请注意,这接近Sql注入漏洞,但由于它是一个int数组,因此是安全的。任意字符串都不安全,但无法将Sql语句嵌入整数(或datetime、boolean等)中

注意:我通常不赞成使用未经参数化的查询。但是,在这种情况下,如果我们处理的是整数数组,您可以这样做,这样会更有效。但是,鉴于每个人似乎都想降低答案的级别,因为它不符合有效建议的标准,我会这样做提交另一个表现糟糕但可能在LINK2SQL中运行的答案

如您的问题所述,假设您有一个整数数组,您可以使用以下代码返回一个字符串,该字符串将包含SQL将接受的逗号分隔列表:

private string SQLArrayToInString(Array a)
{
 StringBuilder sb = new StringBuilder();
 for (int i = 0; i < a.GetUpperBound(0); i++)
  sb.AppendFormat("{0},", a.GetValue(i));
 string retVal = sb.ToString();
 return retVal.Substring(0, retVal.Length - 1);
}
私有字符串SQLArrayToInString(数组a)
{
StringBuilder sb=新的StringBuilder();
for(int i=0;i
然后,我建议您跳过尝试参数化命令,因为这是一个int数组,只需使用:

command.CommandText = @"SELECT id,
            startDateTime, endDateTime From
            tb_bookings WHERE buildingID IN
            (" + SQLArrayToInString(buildingIDs) + ") AND startDateTime <=
            @fromDate";
command.CommandText=@“选择id,
startDateTime,endDateTime From
buildingID所在的tb\U预订
(“+SQLArrayInstring(buildingId)+”)和startDateTime
[网络方法]

公共迷你事件[]getAdminEvents(int buildingID,DateTime startDate)

SqlParameter BuildingId=新的SqlParameter(“@BuildingId”,BuildingId)


也许我说得太详细了,但是这个方法只接受一个int,而不是一个int数组。如果你希望传入一个数组,你需要更新你的方法定义以拥有一个int数组。一旦你得到了这个数组,如果你打算在SQL查询中使用它,你需要将数组转换成字符串。

首先你需要一个fu操作和存储过程。该函数将拆分数据并返回一个表:

CREATE function IntegerCommaSplit(@ListofIds nvarchar(1000))
returns @rtn table (IntegerValue int)
AS
begin
While (Charindex(',',@ListofIds)>0)
Begin
    Insert Into @Rtn 
    Select ltrim(rtrim(Substring(@ListofIds,1,Charindex(',',@ListofIds)-1)))
    Set @ListofIds = Substring(@ListofIds,Charindex(',',@ListofIds)+len(','),len(@ListofIds))
end
Insert Into @Rtn 
    Select  ltrim(rtrim(@ListofIds))
return 
end
接下来,您需要一个存储过程来使用它:

create procedure GetAdminEvents 
    @buildingids nvarchar(1000),
    @startdate datetime
as
SELECT id,startDateTime, endDateTime From
            tb_bookings t INNER JOIN 
dbo.IntegerCommaSplit(@buildingids) i
on i.IntegerValue = t.id
 WHERE startDateTime <= @fromDate
这远远超出了你的问题,但它会做你需要的


注意:如果传入任何不是int的内容,整个数据库函数都将失败。我将错误处理留给最终用户作为练习。

一种超快速XML方法,不需要不安全的代码或用户定义的函数:

可以使用存储过程并传递以逗号分隔的建筑ID列表:

Declare @XMLList xml
SET @XMLList=cast('<i>'+replace(@buildingIDs,',','</i><i>')+'</i>' as xml)
SELECT x.i.value('.','varchar(5)') from @XMLList.nodes('i') x(i))
Declare@xmlsistxml
将@XMLList=cast(“”+replace(@buildingIDs,“”,“”)+设置为xml)
从@XMLList.nodes('i')x(i))中选择x.i.value('.','varchar(5'))

所有的功劳都归Guru所有。您可以使用它。在SQLServer中执行以在数据库上创建函数(仅一次):

如果存在(
挑选*
来自sysobjects
其中name='FN_retrona_ID_FROM_VARCHAR_TO_TABLE_INT')
开始
将函数FN\u retrona\u ID\u从\u VARCHAR\u拖放到\u TABLE\u INT
结束
去
创建函数[dbo]。FN_retrona_ID_FROM_VARCHAR_TO_TABLE_INT(@IDList VARCHAR(8000))
返回
@IDListTable(ID INT)
作为
开始
声明
--@IDList VARCHAR(100),
@最后一次通信INT,
@下一个命令,
@EndOfStringPosition INT,
@StartToStringPosition INT,
@LengthOfString INT,
@IDString VARCHAR(100),
@IDValue INT
--SET@IDList='11,12113'
设置@LastCommaPosition=0
设置@nextCommandPosition=-1
如果LTRIM(RTRIM(@IDList))“”
开始
而(@nextCommand位置0)
开始
设置@NextCommaPosition=CHARINDEX(',',@IDList,@lastcomaposition+1)
如果@NextCommandPosition=0
设置@EndOfStringPosition=LEN(@IDList)
其他的
设置@EndOfStringPosition=@nextcommposition-1
设置@StartOfStringPosition=@lastcompaposition+1
设置@LengthOfString=(@EndOfStringPosition+1)-@StartOfStringPosition
设置@IDString=SUBSTRING(@IDList、@StartOfStringPosition、@LengthOfString)
如果@IDString“”
插入@IDListTable值(@IDString)
设置@LastCommaPosition=@nextcommposition
结束--WHILE(@nextCommand位置0)
结束--如果LTRIM(RTRIM(@IDList))“”
返回
错误块:
返回
结束-函数
创建函数后,必须在代码中调用此函数:

[WebMethod]
        public MiniEvent[] getAdminEvents(int[] buildingIDs, DateTime startDate)
        command.CommandText = @"exec GetAdminEvents";
 SqlParameter buildID= new SqlParameter("@buildingIDs", buildingIDs);
command.CommandText = @"SELECT id,
                        startDateTime, endDateTime From
                        tb_bookings WHERE buildingID IN
                        (SELECT ID FROM FN_RETORNA_ID_FROM_VARCHAR_TO_TABLE_INT(@buildingIDs))) AND startDateTime <=
                        @fromDate";

command.Parameters.Add(new SqlParameter(){
                           DbType = DbType.String,
                           ParameterName = "@buildingIDs",
                           Value = "1,2,3,4,5" //Enter the parameters here separated with commas
                       });
command.CommandText=@“选择id,
startDateTime,endDateTime From
buildingID所在的tb\U预订

(从FN_retrona_ID_从_VARCHAR_到_TABLE_INT(@buildingIDs))中选择ID,然后startDateTime我使用这种方法,并且对我有效

My variable act=字符串处的ID列表

act=“1、2、3、4”


我想出了一个Linq解决方案。它会自动将列表中的所有项目作为参数@item0、@item1、@item2、@item3等插入

[WebMethod]
public MiniEvent[] getAdminEvents(Int32[] buildingIDs, DateTime startDate)
{
    // Gets a list with numbers from 0 to the max index in buildingIDs,
    // then transforms it into a list of strings using those numbers.
    String idParamString = String.Join(", ", (Enumerable.Range(0, buildingIDs.Length).Select(i => "@item" + i)).ToArray());
    command.CommandText = @"SELECT id,
                        startDateTime, endDateTime From
                        tb_bookings WHERE buildingID IN
                        (" + idParamString + @") AND startDateTime <=
                        @fromDate";
    // Reproduce the same parameters in idParamString 
    for (Int32 i = 0; i < buildingIDs.Length; i++)
            command.Parameters.Add(new SqlParameter ("@item" + i, buildingIDs[i]));
    command.Parameters.Add(new SqlParameter("@fromDate", startDate);
    // the rest of your code...
}
[WebMethod]
公共迷你事件[]getAdminEvents(Int32[]buildingIDs
 command = new SqlCommand("SELECT x FROM y WHERE x.id IN (@actions)", conn);    
 command.Parameters.AddWithValue("@actions", act);
 command.CommandText = command.CommandText.Replace("@actions", act);
[WebMethod]
public MiniEvent[] getAdminEvents(Int32[] buildingIDs, DateTime startDate)
{
    // Gets a list with numbers from 0 to the max index in buildingIDs,
    // then transforms it into a list of strings using those numbers.
    String idParamString = String.Join(", ", (Enumerable.Range(0, buildingIDs.Length).Select(i => "@item" + i)).ToArray());
    command.CommandText = @"SELECT id,
                        startDateTime, endDateTime From
                        tb_bookings WHERE buildingID IN
                        (" + idParamString + @") AND startDateTime <=
                        @fromDate";
    // Reproduce the same parameters in idParamString 
    for (Int32 i = 0; i < buildingIDs.Length; i++)
            command.Parameters.Add(new SqlParameter ("@item" + i, buildingIDs[i]));
    command.Parameters.Add(new SqlParameter("@fromDate", startDate);
    // the rest of your code...
}