Wie schreibt man eine parametrisierte Where-In-SQL-Abfrage in Entity Framework? Ich habe folgendes versucht:
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();
Aber wie erwartet, wirft DateParam einen Fehler aus, da ein einzelner Wert erwartet wird.
Dies ist kein spezifisches Problem für das Entity-Framework. Sie können dieses Problem lösen, indem Sie Ihre eigenen Parameternamen dynamisch generieren.
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));
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());
Die resultierende Abfrage, die an den SQL-Server gesendet wird, sieht folgendermaßen aus:
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
Im Allgemeinen möchten Sie die Bearbeitung von Zeichenfolgen beim Schreiben von Abfragen vermeiden. Ich glaube jedoch, dass dieses Beispiel sicher vor SQL-Injektion ist.
So schreiben Sie Ihre Abfrage in SQL.
select *
from MyTable
where dateColumn in ('2014-01-01', '2014-02-01', '2014-03-01')
Man darf also nichts anderes erwarten, als diese durch Klammern abgegrenzte Zeichenkette darstellen zu müssen.
var dateQueryString = string.Join(",", chartModelData.GetFormattedDateList());
// Dates shall be returned as DateTime.ToShortDateTimeString() as follows:
// '2014-01-01', '2014-02-01', '2014-03-01'
Dann bleibt nur noch übrig, es in Klammern einzuwickeln.
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";
Geben Sie die Parameterwerte für jeden benannten Parameter und voilà an! Das soll es tun!
Ich würde stattdessen ein gespeichertes proc schreiben, das Ihre Parameter akzeptiert, und dann das proc zu Ihrem edmx hinzufügen.
Dann ändern Sie im edmx -> Model Browser -> Function Imports -> ... den Rückgabetyp der gespeicherten proc in SPCDataSeqCntInfo.
Das Entity Framework sorgt dann für die Übergabe Ihrer Parameter.
z.B.
public static List<SPCDataSeqCntInfo> GetSPCDataSeqCntInfo(DateTime dateParam, string lineCode, int modelNum, int equipmentNumber, int lotNum)
{
using (var db = new NameOfMyEntites())
{
return db.sp_GetSPCDataSeqCntInfo(dateParam, lineCode, modelNum, equipmentNumber, lotNum).ToList();
}
}