EF Core ExecuteSqlCommand and parameters - c#

I have to execute an sql command on ef core 1.1.2:
var projectParam = new SqlParameter("#projectid", SqlDbType.UniqueIdentifier).Value = inventory.ProjectId;
var locationParam = new SqlParameter("#locationid", SqlDbType.UniqueIdentifier).Value = location.Id;
var scanOrderParam = new SqlParameter("#scanorder", SqlDbType.Int).Value = scanOrder;
_ctx.Database.ExecuteSqlCommand("update Inventories set ScanOrder=ScanOrder+1 where ProjectId = '#projectid' AND LocationId = '#locationid' AND ScanOrder>'#scanorder';",
parameters: new[] {
projectParam, locationParam, scanOrderParam
});
It throws the exception:
An unhandled exception has occurred: Conversion failed when converting from a character string to uniqueidentifier.
If I write ScanOrder>#scanorder into the command it says that scanorder parameter must be declared. Which is an int.
If I don't use apostrophes at projectid and locationid it throws the exception parameter must be declared.
What is the proper way for using parameters with ef core?
Edit (solution):
The problem was the way I declared parameters and give them values. If I use this form it works:
var projectParam = new SqlParameter("#projectid", SqlDbType.UniqueIdentifier);
projectParam.Value = inventory.ProjectId;
var locationParam = new SqlParameter("#locationid", SqlDbType.UniqueIdentifier);
locationParam.Value = location.Id;
var scanOrderParam = new SqlParameter("#scanorder", SqlDbType.Int);
scanOrderParam.Value = scanOrder;

var queryItem = new SqlParameter("#table", SqlDbType.Char) {Value = yourValue};

Related

How can i call OUT parameter in PROCEDURE via Npgsql

How can i call OUT parameter in PROCEDURE via Npgsql
I am getting this error when i run below code
-- PostgreSQL 14 -> PROCEDURE
CREATE OR REPLACE PROCEDURE sp_add_users_new(arrJsnUsers JSON[], jOut OUT JSON) AS $$
DECLARE
intSpStatus INT;
v json;
BEGIN
FOREACH v IN ARRAY arrJsnUsers
LOOP
INSERT INTO tbl_user (vhr_name, vhr_password, sin_record_status)
VALUES(v->>'strName', v->>'strPassword', (v->>'intRecordStatus')::SMALLINT);
END LOOP;
COMMIT;
intSpStatus = 1;
jOut['intSpStatus'] = intSpStatus;
END;
$$ LANGUAGE plpgsql
--Dot net core 5
using (NpgsqlConnection objCon = new NpgsqlConnection("..."))
{
objCon.Open();
using (NpgsqlCommand objSqlCommand = new NpgsqlCommand("CALL sp_add_users_new(:p1, :p2)", objCon))
{
// Parameters
NpgsqlParameter[] lstSqlParameter = {
new NpgsqlParameter("p1", NpgsqlDbType.Array|NpgsqlDbType.Json) {
Value = lstUsers,
DataTypeName = "arrJsnUsers"
},
new NpgsqlParameter("p2", NpgsqlDbType.Json) {
Value = jOut,
DataTypeName = "jOut",
Direction = ParameterDirection.Output
},
};
objSqlCommand.Parameters.AddRange(lstSqlParameter);
// Execute
IDataReader objDataReader = objSqlCommand.ExecuteReader();
}
objCon.Close();
}
--Error
42703: column "p2" does not exist
Below is a sample which works - it's recommended to read the Npgsql docs on this. Some comments:
You don't specify the output parameter in SQL - just pass a NULL as per the PostgreSQL docs.
Since #p2 is an output parameter, it makes no sense to specify its value (jOut1 above).
DataTypeName (jOut above) also doesn't make sense here; that's used to indicate to Npgsql which PG type to send for input parameters (similar to NpgsqlDbType).
using var objCon = new NpgsqlConnection("Host=localhost;Username=test;Password=test");
objCon.Open();
using var objSqlCommand = new NpgsqlCommand("CALL sp_add_users_new(#p1, NULL)", objCon);
// Parameters
var lstUsers = new[] { #"{ ""Foo"": ""Bar"" }" };
NpgsqlParameter[] lstSqlParameter = {
new NpgsqlParameter("p1", NpgsqlDbType.Array|NpgsqlDbType.Json) { Value = lstUsers, DataTypeName = "arrJsnUsers"},
new NpgsqlParameter("p2", NpgsqlDbType.Json) { Direction = ParameterDirection.Output},
};
objSqlCommand.Parameters.AddRange(lstSqlParameter);
// Execute
IDataReader objDataReader = objSqlCommand.ExecuteReader();
Console.WriteLine(objSqlCommand.Parameters[1].Value);

The SqlParameter is already contained by another SqlParameterCollection using SqlQuery Class in .Net

I am invoking a stored procedure as follows:
var filterParameter = new SqlParameter("Column", filter);
var criteriaParameter = new SqlParameter("Criteria", criteria);
var countParameter = new SqlParameter("ItemPerPage", count);
var tenantParameter = new SqlParameter("TenantId", tenantId);
var pageParameter = new SqlParameter("Page", page);
string sortTypeQuery = "DESC";
if (sortType == OrderByType.Ascending) sortTypeQuery = "ASC";
var sortTypeParameter = new SqlParameter("SortType", sortTypeQuery);
var tableParameter = new SqlParameter("Table", "TenantSubscribers");
return await Context.Database.SqlQuery<string>(
"EXEC [dbo].[Filters] #Column, #Criteria, #ItemPerPage, #TenantId, #SortType, #Table, #Page",
filterParamter, criteriaParameter, countParameter, tenantParameter, sortTypeParameter, pageParameter,
tableParameter, pageParameter).ToListAsync();
As a result it generates an exception:
The SqlParameter is already contained by another SqlParameterCollection
You have pageParameter two times. Should be only once.
You are providing pageParameter twice.

Count line in SQL query

I try to count line in my SQL query.
It works without parameter. For example, if I assign directly FIOForm = 'SmithJJ'. I really don't understand what I'm doing wrong.
Exception: the SqlParameter is already contained by another SqlParameterCollection
int kolNar = 0;
System.Data.SqlClient.SqlParameter Name = new System.Data.SqlClient.SqlParameter("#Name", System.Environment.UserName);
var pushStat = db.Database.SqlQuery<Reestr>("select * from Reestr where FIOForm = #Name and Status = 'Executed'", Name);
foreach (var u in pushStat)
{
kolNar = pushStat.Count();
}
if (kolNar > 0)
MessageBox.Show(kolNar.ToString());
I suppose you can call:
Dispose();
before
System.Data.SqlClient.SqlParameter Name = new System.Data.SqlClient.SqlParameter("#Name", System.Environment.UserName);

How to get the result of a linq back to a DataTable?

I have problem when copy query linq to same datatable.
DataTable dt_result = filterkontrak.CopyToDataTable();
var query = from q in dt_result.AsEnumerable()
select new
{
ChassisNo = q.Field<string>("ChassisNo"),
Engineno = q.Field<string>("Engineno"),
BuiltYear = q.Field<string>("ManufactureYear"),
VehicleType = q.Field<string>("VehicleType"),
PlatNo = q.Field<string>("LicensePlate"),
Type = q.Field<string>("Type"),
ContractNo = q.Field<string>("Brand"),
ContractDate = q.Field<string>("ContractNo"),
TglGenerate = q.Field<string>("ContractDate"),
FileName = q.Field<string>(FileName),
Status = q.Field<string>("1"),
CreatorID = q.Field<string>(UserId),
LastUserId = q.Field<string>(UserId)
};
DataTable dt_result2 = query.AsEnumerable();
SqlBulkCopy bulkCopy = new SqlBulkCopy(conn.SqlCon());
bulkCopy.DestinationTableName = "TEMP_VMF_LogAssetMngmt";'
Error:
The type 'AnonymousType#1' cannot be used as type parameter 'T' in the
generic type or method
'System.Data.DataTableExtensions.CopyToDataTable(System.Collections.Generic.IEnumerable)'.
Couldy anybody improve my code ?

Parameterize DocumentDB query with IN clause

I have a query somewhat like the following which I'm trying to parameterize:
List<string> poiIDs = /*List of poi ids*/;
List<string> parameterNames = /*List of parameter names*/;
string inClause = string.Join(",", parameterNames);
string query = string.Format("SELECT c.id AS poiID, c.poiName, c.latitude, c.longitude FROM c WHERE c.clusterName = #clusterName AND c.id IN ({0}) AND c.deleted = false", inClause);
IQueryable<POI> queryResult = Client.CreateDocumentQuery<POI>(Collection.SelfLink, new SqlQuerySpec
{
QueryText = query,
Parameters = new SqlParameterCollection()
{
new SqlParameter("#clusterName", "POI"),
// How do I declare the dynamically generated parameters here
// as new SqlParameter()?
}
});
How do I declare the dynamically generated parameters as new SqlParameter() for the Parameters property of SqlQuerySpec in order to create my document query?
You can create dynamic parameterized query like this:
// DocumentDB query
// POINT TO PONDER: create the formatted query, so that after creating the dynamic query we'll replace it with dynamically created "SQL Parameter/s"
var queryText = #"SELECT
us.id,
us.email,
us.status,
us.role
FROM user us
WHERE us.status = #userStatus AND us.email IN ({0})";
// contain's list of emails
IList<string> emailIds = new List<string>();
emailIds.Add("a#gmail.com");
emailIds.Add("b#gmail.com");
#region Prepare the query
// simple parameter: e.g. check the user status
var userStatus = "active";
var sqlParameterCollection = new SqlParameterCollection { new SqlParameter("#userStatus", userStatus) };
// IN clause: with list of parameters:
// first: use a list (or array) of string, to keep the names of parameter
// second: loop through the list of input parameters ()
var namedParameters = new List<string>();
var loopIndex = 0;
foreach (var email in emailIds)
{
var paramName = "#namedParam_" + loopIndex;
namedParameters.Add(paramName);
var newSqlParamter = new SqlParameter(paramName, email);
sqlParameterCollection.Add(newSqlParamter);
loopIndex++;
}
// now format the query, pass the list of parameter into that
if (namedParameters.Count > 0)
queryText = string.Format(queryText, string.Join(" , ", namedParameters));
// after this step your query is something like this
// SELECT
// us.id,
// us.email,
// us.status,
// us.role
// FROM user us
// WHERE us.status = #userStatus AND us.email IN (#namedParam_0, #namedParam_1, #namedParam_2)
#endregion //Prepare the query
// now inject the parameter collection object & query
var users = Client.CreateDocumentQuery<Users>(CollectionUri, new SqlQuerySpec
{
QueryText = queryText,
Parameters = sqlParameterCollection
}).ToList();
The following gives you a SQL query, you can then run in your DocumentDB Collection, to get the Documents by their IDs.
var query = $"SELECT * FROM p WHERE p.id IN ('{string.Join("', '", arrayOfIds)}')";
The DocumentDB SDK doesn't support parameterized IN queries.
Judging from the SO thread in the comment above, SQL does not either. As mentioned in the other thread, you can use LINQ as a workaround.
Why not use the ArrayContains method? Here is an example in node
sqlQuery = {
query: 'SELECT * FROM t WHERE ARRAY_CONTAINS(#idList, t.id)',
parameters: [
{
name: '#idList',
value: ['id1','id2','id3'],
},
],
};

Categories