C# SqlCommand is not sending the right query with parameters - c#

It's a pretty simple problem, but I can't find a solution (not even sure what question to google here).
Here is my code to create the command:
var targetStartDate = "October 2014";//ConfigurationManager.AppSettings["StartDateString"].ToString(CultureInfo.InvariantCulture);
var acceptedStatusCodes = 4;//ConfigurationManager.AppSettings["ImportStatusIds"].ToString(CultureInfo.InvariantCulture);
using (var connection = new SqlConnection(connString))
{
using (var cmd = connection.CreateCommand())
{
cmd.CommandText = #"
SELECT
ai.FirstName,
ai.LastName,
ai.Email,
ai.SSN,
ai.Phone,
ai.Program,
r.FirstName + ' ' + r.LastName AS RepName,
d.Name AS StartDateName,
s.CvId AS CvSySchoolStatusId,
ai.CampusId as SyStudentId
FROM
dbo.aspnet_Users AS u LEFT OUTER JOIN
dbo.ApplicantInfo AS ai ON u.UserId = ai.UserId LEFT OUTER JOIN
dbo.AdmissionReps AS r ON ai.AdmissionsRepId = r.RepId LEFT OUTER JOIN
dbo.ProgramStartDate AS d ON ai.StartDateId = d.CvStartDateId LEFT OUTER JOIN
dbo.CvSySchoolStatus AS s ON ai.CvSySchoolStatusId = s.CvId
where d.Name = '#StartDate'
and CvSySchoolStatusId in (#Statuses)";
cmd.Parameters.AddWithValue("#StartDate", SqlDbType.VarChar).Value = (object) targetStartDate;
cmd.Parameters.AddWithValue("#Statuses", SqlDbType.Int).Value = (object) acceptedStatusCodes;
...
}
....
}
The reader sends the command fine, I can see it go through via SQL profiler:
exec sp_executesql N'
SELECT
ai.FirstName,
ai.LastName,
ai.Email,
ai.SSN,
ai.Phone,
ai.Program,
r.FirstName + '' '' + r.LastName AS RepName,
d.Name AS StartDateName,
s.CvId AS CvSySchoolStatusId,
ai.CampusId as SyStudentId
FROM
dbo.aspnet_Users AS u LEFT OUTER JOIN
dbo.ApplicantInfo AS ai ON u.UserId = ai.UserId LEFT OUTER JOIN
dbo.AdmissionReps AS r ON ai.AdmissionsRepId = r.RepId LEFT OUTER JOIN
dbo.ProgramStartDate AS d ON ai.StartDateId = d.CvStartDateId LEFT OUTER JOIN
dbo.CvSySchoolStatus AS s ON ai.CvSySchoolStatusId = s.CvId
where d.Name = ''#StartDate''
and CvSySchoolStatusId in (#Statuses)'
,N'#StartDate nvarchar(12),#Statuses int'
,#StartDate=N'October 2014'
,#Statuses=4
This query gives me 0 results, but if I take this exact query and just paste in the parameters and run just the query text, I get the expected results. Any idea where I am going wrong here?

You need to remove single quotes around your parameter in string query
this:
where d.Name = '#StartDate'
should be:
where d.Name = #StartDate
No single parameters.

Perhaps it's the extra single quotes around startdate. I think you might want to remove those single quotes and try again. Should look like:
...
where d.Name = #StartDate

Related

Is it possible to use WHERE by some IF condition for PostgreSQL?

I have the following SQL request for a report.
select customers."AppId", second_dep "SecondDeps", first_dep "FirstDeps",
customers_count "Customers", registrations "Registrations"
From (select Count("AppId") as customers_count, "AppId"
FROM "Customers"
join "Advertisers" A on "Customers"."AdvertiserId" = A."AdvertiserId"
join "Categories" C2 on "Customers"."CategoryId" = C2."CategoryId"
where A."Name" in (:AdvertiserNames)
AND C2."Name" = :CategoryName
GROUP BY "AppId"
) as customers
left join
(select C."AppId", count(CE.*) as second_dep
from "CustomerEvents" as CE
inner join "Customers" C on CE."CustomerId" = C."CustomerId"
WHERE "EventType" = 'deposit'
and "Again" = TRUE
GROUP BY C."AppId") as dep2 on customers."AppId" = dep2."AppId"
left join
(select C."AppId", count(CE.*) as first_dep
from "CustomerEvents" as CE
inner join "Customers" C on CE."CustomerId" = C."CustomerId"
WHERE "EventType" = 'deposit'
and "Again" = false
GROUP BY C."AppId") as dep on customers."AppId" = dep."AppId"
left join
(select C."AppId", count(CE.*) as registrations
from "CustomerEvents" as CE
inner join "Customers" C on CE."CustomerId" = C."CustomerId"
WHERE "EventType" = 'registration'
GROUP BY C."AppId") as regs on regs."AppId" = customers."AppId";
The string with problem is
where A."Name" in (:AdvertiserNames)
I would like to skip it if AdvertiserNames is empty. Is it possible? Ok, I can check it on the code side, but this way will leads me to copy whole request with some small difference (I mean if AdvertiserNames is empty run SQL without where A."Name" in (:AdvertiserNames)). Or I can use concatenation to get suitable SQL. I dont like this way too.
About my technology stack. It's .NET Core 2.2 with PostgreSQL. Here is the code of whole report method:
public IQueryable<ByApplicationsReportModel> ByApplications(string category, List<string> advertisers)
{
var rawSql = new RawSqlString(#"
select customers.""AppId"", second_dep ""SecondDeps"", first_dep ""FirstDeps"",
customers_count ""Customers"", registrations ""Registrations""
From (select Count(""AppId"") as customers_count, ""AppId""
FROM ""Customers""
join ""Advertisers"" A on ""Customers"".""AdvertiserId"" = A.""AdvertiserId""
join ""Categories"" C2 on ""Customers"".""CategoryId"" = C2.""CategoryId""
where A.""Name"" in (#AdvertiserNames)
AND C2.""Name"" = #CategoryName
GROUP BY ""AppId""
) as customers
left join
(select C.""AppId"", count(CE.*) as second_dep
from ""CustomerEvents"" as CE
inner join ""Customers"" C on CE.""CustomerId"" = C.""CustomerId""
WHERE ""EventType"" = 'deposit'
and ""Again"" = TRUE
GROUP BY C.""AppId"") as dep2 on customers.""AppId"" = dep2.""AppId""
left join
(select C.""AppId"", count(CE.*) as first_dep
from ""CustomerEvents"" as CE
inner join ""Customers"" C on CE.""CustomerId"" = C.""CustomerId""
WHERE ""EventType"" = 'deposit'
and ""Again"" = false
GROUP BY C.""AppId"") as dep on customers.""AppId"" = dep.""AppId""
left join
(select C.""AppId"", count(CE.*) as registrations
from ""CustomerEvents"" as CE
inner join ""Customers"" C on CE.""CustomerId"" = C.""CustomerId""
WHERE ""EventType"" = 'registration'
GROUP BY C.""AppId"") as regs on regs.""AppId"" = customers.""AppId""");
var advertisersParam = new NpgsqlParameter("AdvertiserNames",
string.Join(",", advertisers) );
var categoryParam = new NpgsqlParameter("CategoryName", category);
return _context.ByApplicationsReportModels
.FromSql(rawSql, categoryParam, advertisersParam);
}
Any ideas?
You might try changing where A.""Name"" in (#AdvertiserNames) to where (A.""Name"" in (#AdvertiserNames) or #AdvertiserNames = '').
Instead of concatenating your advertisers into a string, you could just pass an array of strings directly to your query:
var advertisersParam = new NpgsqlParameter("AdvertiserNames", advertisers));
In SQL, instead of using the x IN (#advertisers) construct, you would need to change to x = ANY (#advertisers).
Note: you would still need an additional clause if you want the check to pass when #advertisers is empty.

SQL to LINQ with outer apply

I am not able convert sql to linq because of outer apply
select * from dbo.Table1 l
inner join dbo.Table2 d on d.LoanId = l.Id
inner join dbo.Cash cOriginal on cOriginal.DealId = d.Id and cOriginal.IsOriginal = 1
outer apply (select top 1 * from dbo.Cash cActive
where cActive.DealId = d.ID and cActive.IsOriginal = 0
order by cActive.CreatedOn desc) cActiveRes
I am started something like this:
var q = from x in _repo.Queryable<Table1>()
join Table2 in _repo.Queryable<Table2>() on x.Id equals Table2.LoanId
join cOriginal in _repo.Queryable<Cash>() on Table2.Id equals
cOriginal.DealId
// now Outer Apply should come?
// fActive in _repo.Queryable<Cash>()
The easiest way it to run your SQL query directly letting EF to materialize the result. It might look like this (depending on version of EF you use):
var result = ((IObjectContextAdapter)_repo).ObjectContext.ExecuteStoreQuery<Table1>(
#"SELECT your query here");

MySQL Inner Join Syntax Error in C#

Anyone know why got syntax error? I think there are no reserve words inside right?
C# Command
cmd.CommandText = "SELECT ordertable._name, ordertable.quantity, food_menu.food_price, beverage_menu.beverage_price" +
"FROM ordertable" +
"INNER JOIN food_menu ON ordertable._name = food.foodname" +
"INNER JOIN beverage_menu ON beverage_menu.beverage_name' = ordertable._name" +
"WHERE ordertable.tablenum = '1'";
Error:
You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use
near 'JOIN food_menu ON ordertable._name = food.foodnameINNER JOIN
beverage_menu ON be' at line 1
You are missing spaces. At the moment your query will be like FROM ordertableINNER JOIN food_menu .... You could use the multiline syntax to make it simpler
cmd.CommandText = #"SELECT ordertable._name, ordertable.quantity, food_menu.food_price, beverage_menu.beverage_price
FROM ordertable
INNER JOIN food_menu ON ordertable._name = food_menu.foodname
INNER JOIN beverage_menu ON beverage_menu.beverage_name = ordertable._name
WHERE ordertable.tablenum = 1";
Remove unnecessary concatenation from string, you are getting an error because your query needs some spaces which you have not specified before join.
cmd.CommandText = "SELECT ordertable._name,
ordertable.quantity,
food_menu.food_price,
beverage_menu.beverage_price
FROM ordertable
INNER JOIN food_menu
ON ordertable._name = food.foodname
INNER JOIN beverage_menu
ON beverage_menu.beverage_name = ordertable._name
WHERE ordertable.tablenum = 1";

joining to tables in a query for ASP.NET C# ~ multi-part-identifier-could-not-be-bound

Among other answers I have looked at the following:
The multi-part identifier could not be bound
However tying to use that answer I was still not able to make my grouping work.
The following query works:
string query = #"SELECT
ud.FirstName,
ud.LastName,
p.Name AS Product,
p.ItemNumber,
sc.AmountPurchased * sc.Price AS Total,
sc.DatePurchased,
sc.IsInCart AS [NotShipped]
FROM
ShoppingCarts sc INNER JOIN
UserDetails ud ON sc.ClientID = ud.Guid Left
OUTER JOIN
Products p ON sc.ProductID = p.ProductsId
WHERE sc.DatePurchased >= #date1
AND sc.DatePurchased <= #date2
AND sc.IsInCart = #shipped ";
but when I try to group it like this:
string query = #"SELECT ud.LastName, sc.DatePurchased, SUM(Total)
FROM(
SELECT
ud.FirstName,
ud.LastName,
p.Name AS Product,
p.ItemNumber,
sc.AmountPurchased * sc.Price AS Total,
sc.DatePurchased,
sc.IsInCart AS [NotShipped]
FROM
ShoppingCarts sc INNER JOIN
UserDetails ud ON sc.ClientID = ud.Guid Left
OUTER JOIN
Products p ON sc.ProductID = p.ProductsId
WHERE sc.DatePurchased >= #date1
AND sc.DatePurchased <= #date2
AND sc.IsInCart = #shipped
) AS result
GROUP BY ud.LastName, sc.DatePurchased";
I get the "multi-part identifier ud.LastName, etc cannot be bound"
When doing nested selects the aliases do not propagate out of their scope. This is more evident when looking at the equivalent CTE query (assuming you're using MS SQL Server / T-SQL):
;WITH
(
SELECT
ud.FirstName,
ud.LastName,
p.Name AS Product,
p.ItemNumber,
sc.AmountPurchased * sc.Price AS Total,
sc.DatePurchased,
sc.IsInCart AS [NotShipped]
FROM
ShoppingCarts sc INNER JOIN
UserDetails ud ON sc.ClientID = ud.Guid Left
OUTER JOIN
Products p ON sc.ProductID = p.ProductsId
WHERE sc.DatePurchased >= #date1
AND sc.DatePurchased <= #date2
AND sc.IsInCart = #shipped
) AS Result
SELECT
LastName,
DatePurchased,
SUM(Total)
FROM Result
GROUP BY
LastName,
DatePurchased
So your problem is solved by removing the ud and sc identifiers from the outer select and group by.

Query with parameters in C# (using SQL Server)

I have a problem with query in C#.
I have this part of code :
string query1 = #"
SELECT TOP #howManyRows * FROM
(
SELECT
PRODUCTCODE_.ID_ AS PRODUCTCODE_ID_,
PRODUCTCODE_.CATEGORY_ AS CATEGORY_,
PRODUCTCODE_.DESCRIPTION_ AS DESCRIPTION_,
PRODUCTCODE_.MANUFACTURER_ AS MANUFACTURER_,
PRODUCTLINE_.CREATION_DATE_ AS CREATION_DATE_,
ROW_NUMBER() OVER (ORDER BY PRODUCTCODE_.CATEGORY_) AS ROWNUMBER_,
TOTALROWS_ = COUNT(*) OVER()
FROM
PRODUCTCODE_
INNER JOIN
PRODUCTLINE_ ON PRODUCTLINE_.ID_ = PRODUCTCODE_.PRODUCTLINE_ID_
) _tmpList
WHERE
ROWNUMBER_ >= #startingWith
ORDER BY CATEGORY_
";
SqlParameter param1 = new SqlParameter();
param1.ParameterName = "#howManyRows";
param1.Value = resultPerPage; //`resultPerPage` is an integer function parameter
SqlParameter param2 = new SqlParameter();
param2.ParameterName = "#startingWith";
param2.Value = startsWith; //`startWith` is an integer function parameter
SqlCommand cmd = new SqlCommand( query1, connect );
cmd.Parameters.Add( param1 );
cmd.Parameters.Add( param2 );
When debug arrived to SqlDataReader reader = cmd.ExecuteReader(); then the exception is thrown:
Incorrect syntax near #howManyRows ...
Why ? I defined and added howManyRows with Parameters property.
Where is my mistakes ?
Change your top query syntax from
SELECT TOP #howManyRows * FROM
to
SELECT TOP (#howManyRows) * FROM
Try wrapping the parameter specified next to TOP in parentheses, like so:
SELECT TOP (#howManyRows) * FROM
You need parenthesis to parametrise TOP
SELECT TOP (#howManyRows) * FROM
This will work.
SELECT
PRODUCTCODE_.ID_ AS PRODUCTCODE_ID_,
PRODUCTCODE_.CATEGORY_ AS CATEGORY_,
PRODUCTCODE_.DESCRIPTION_ AS DESCRIPTION_,
PRODUCTCODE_.MANUFACTURER_ AS MANUFACTURER_,
PRODUCTLINE_.CREATION_DATE_ AS CREATION_DATE_,
ROW_NUMBER() OVER (ORDER BY PRODUCTCODE_.CATEGORY_) AS ROWNUMBER_,
TOTALROWS_ = COUNT(*) OVER()
FROM
PRODUCTCODE_
INNER JOIN
PRODUCTLINE_ ON PRODUCTLINE_.ID_ = PRODUCTCODE_.PRODUCTLINE_ID_
) _tmpList
WHERE
ROWNUMBER_ between #startingWith and (#startingWith + #howManyRows)
ORDER BY CATEGORY_
You need to add a couple of parenthesis to make it work.
SELECT TOP (#howManyRows) * FROM
Use SELECT TOP(#howManyRows) syntax
You can do
SELECT TOP (#howManyRows) * FROM
But this really depends on the Database Server you are using. For example, this is only supported from MSSQL Server 2005 upwards
If this does not work you can do the following...
You can include this into your query string. But this can result in Sql Injection if you don't check the value of your variable.
Sample
int top = 10;
Int32.TryParse(howManyRows.ToString(), out top);
string query1 = "SELECT TOP " + top.ToString() + #" * FROM
(
SELECT
PRODUCTCODE_.ID_ AS PRODUCTCODE_ID_,
PRODUCTCODE_.CATEGORY_ AS CATEGORY_,
PRODUCTCODE_.DESCRIPTION_ AS DESCRIPTION_,
PRODUCTCODE_.MANUFACTURER_ AS MANUFACTURER_,
PRODUCTLINE_.CREATION_DATE_ AS CREATION_DATE_,
ROW_NUMBER() OVER (ORDER BY PRODUCTCODE_.CATEGORY_) AS ROWNUMBER_,
TOTALROWS_ = COUNT(*) OVER()
FROM
PRODUCTCODE_
INNER JOIN
PRODUCTLINE_ ON PRODUCTLINE_.ID_ = PRODUCTCODE_.PRODUCTLINE_ID_
) _tmpList
WHERE
ROWNUMBER_ >= #startingWith
ORDER BY CATEGORY_
";

Categories