How do you write a parameterized where-in raw sql query in Entity Framework? I've tried the following:
string dateQueryString = String.Join(",", chartModelData.GetFormattedDateList()); //Dates returned in format of 20140402,20140506,20140704 const string selectQuery = @"SELECT MAX(DATA_SEQ) AS MaxSeq, MIN(DATA_SEQ) AS MinSeq, COUNT(1) AS TotSampleCnt FROM SPCDATA_TB WHERE DATA_WDATE IN @DateParam AND LINE_CODE = @LineCode AND MODEL_NO = @ModelNumber AND LOT_NO = @LotNumber AND EQUIP_NO LIKE @EquipNumber"; SPCDataSeqCntInfo dataSeqCntInfo = _dbContext.Database.SqlQuery<SPCDataSeqCntInfo>( selectQuery, new SqlParameter("@DateParam", dateQueryString), new SqlParameter("@LineCode", chartModelData.LineCode), new SqlParameter("@ModelNumber", chartModelData.ModelNum), new SqlParameter("@EquipNumber", equipmentNumber), new SqlParameter("@LotNumber", chartModelData.LotNum) ).SingleOrDefault() ?? new SPCDataSeqCntInfo();
But as expected, it throws an error on DateParam because it's expecting a single value.
Declare statements start with the keyword DECLARE , followed by the name of the parameter (starting with a question mark) followed by the type of the parameter and an optional default value. The default value must be a literal value, either STRING , NUMERIC , BOOLEAN , DATE , or TIME .
Parameterized Queries. You are always advised to parameterize user input to prevent the possibility of a SQL injection attack being successful. Entity Framework Core will parameterize SQL if you use format strings with FromSqlRaw or string interpolation with the FromSqlInterpolated method: // Format string.
The first way to parameterize a query is by mapping the query. To map a parameter the first thing you need to do is add a parameter mapping from the Parameters tab. Then find the value you want map the parameter to, select the variable and hit OK. You have now mapped your parameter to the Expected Query Value.
Entity Framework Core provides the DbSet. FromSql() method to execute raw SQL queries for the underlying database and get the results as entity objects. The following example demonstrates executing a raw SQL query to MS SQL Server database. var context = new SchoolContext(); var students = context.
This isn't a problem specific to entity-framework, you can solve it by generating your own parameter names dynamically.
var parameters = new List<SqlParameter> { new SqlParameter("@DateParam", dateQueryString), new SqlParameter("@LineCode", chartModelData.LineCode), new SqlParameter("@ModelNumber", chartModelData.ModelNum), new SqlParameter("@EquipNumber", equipmentNumber), new SqlParameter("@LotNumber", chartModelData.LotNum) }; var dateParameters = chartModelData .GetFormattedDateList() .Select((date, index) => new SqlParameter("@date" + index, date)); .ToList(); parameters.AddRange(dateParameters); var inValues = string.Join(", ", dateParameters.Select(p => p.ParameterName)); var query = @"SELECT MAX(DATA_SEQ) AS MaxSeq, MIN(DATA_SEQ) AS MinSeq, COUNT(1) AS TotSampleCnt FROM SPCDATA_TB WHERE DATA_WDATE IN (" + inValues + @") AND LINE_CODE = @LineCode AND MODEL_NO = @ModelNumber AND LOT_NO = @LotNumber AND EQUIP_NO LIKE @EquipNumber"; var myResult = _dbContext.Database .SqlQuery<SPCDataSeqCntInfo>(query, parameters.ToArray());
The resulting query sent to SQL-Server will look like the following:
SELECT MAX(DATA_SEQ) AS MaxSeq, MIN(DATA_SEQ) AS MinSeq, COUNT(1) AS TotSampleCnt FROM SPCDATA_TB WHERE DATA_WDATE IN (@date0, @date1, @date2) AND LINE_CODE = @LineCode AND MODEL_NO = @ModelNumber AND LOT_NO = @LotNumber AND EQUIP_NO LIKE @EquipNumber
Generally, you want to avoid doing string manipulation when writing queries, however, I believe this example is safe from sql-injection.
Here's how you would write your query in SQL.
select * from MyTable where dateColumn in ('2014-01-01', '2014-02-01', '2014-03-01')
So one shall not expect otherwise than having to represent this string entirely delimited by parenthesis.
var dateQueryString = string.Join(",", chartModelData.GetFormattedDateList()); // Dates shall be returned as DateTime.ToShortDateTimeString() as follows: // '2014-01-01', '2014-02-01', '2014-03-01'
Then only remains to wrap it in parenthesis.
var sql = @"select max(data_seq) as MaxSeq , min(data_seq) as MinSeq , count(1) as TotSampleCnt from spcdata_tb where data_wadate in (@DateParam) and line_code = @LineCode and model_no = @ModelNumber and lot_no = @LotNumber and equip_no like @EquipNumber";
Provide the parameters values for each named parameter, and voilà! This shall do it!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With