如何使用实体框架SqlQuery保护SQL参数
本文关键字:保护 SQL 参数 SqlQuery 框架 何使用 实体 | 更新日期: 2023-09-27 18:25:25
我有一个方法,它应该使用未知数量的id。我几乎完成了这个方法,但由于明显的原因,它还不安全,我知道我可以写自己的方法来去除参数,但使用一些内置方法会更方便。
这是的方法
public static List<LocationModel> FetchCitiesByAreas(IEnumerable<string> areas)
{
using (var db = new BoligEnt())
{
var sqlQuery = new StringBuilder();
var first = true;
sqlQuery.Append("SELECT DISTINCT a.city AS City, a.zip AS Zip ");
sqlQuery.Append("FROM zip_city AS a ");
sqlQuery.Append("WHERE country = 1 ");
foreach (var d in areas)
{
if (first)
{
sqlQuery.Append("AND a.area_id = '" + d + "'");
first = false;
}
else
{
sqlQuery.Append("OR a.area_id = '" + d + "'");
}
}
return db.Database.SqlQuery<LocationModel>(sqlQuery.ToString()).ToList();
}
}
我知道它内置了这个功能,但正如我之前所说,我不知道中会有多少ID
db.Database.SqlQuery<LocationModel>("SELECT * FROM table WHERE id = @p0 ;", id).ToList();
感谢
虽然我完全同意paqogomez的观点,因为您应该只使用LINQ来执行查询,但.SqlQuery
能够获取参数数组。你可以把你的声明改成这样:
var sqlQuery = new StringBuilder();
sqlQuery.Append("SELECT DISTINCT a.city AS City, a.zip AS Zip ");
sqlQuery.Append("FROM zip_city AS a ");
sqlQuery.Append("WHERE country = 1 ");
for (int i = 0; i < areas.Count; i++)
{
if (i == 0)
{
sqlQuery.Append("AND (a.area_id = @p" + i.ToString());
}
else
{
sqlQuery.Append(" OR a.area_id = @p" + i.ToString());
}
}
sqlQuery.Append(")");
var results = db.Database.SqlQuery<LocationModel>(sqlQuery.ToString(), areas.ToArray()).ToList();
我为您的查询添加了所需的缺失括号,以正确地筛选出OR结果。我还假设areas
有点像List
,或者至少你可以很容易地从中得到计数。
为什么不直接使用Linq?
var locations = (from zip in db.zip_city
where areas.Contains(zip.area_id) && zip.Country == 1
select new LocationModel{
City = zip.City,
Zip = zip.Zip
})
.Distinct()
.ToList();
如果你仍然想参数化你的查询,你需要使用EntityCommand
还要注意,您的查询将失败,因为您没有在OR
语句周围加括号。
我建议你这样构建sql:
string sqlQuery =
@"SELECT DISTINCT a.city AS City, a.zip AS Zip
FROM zip_city AS a
WHERE country = 1 AND (1=0 "
for (int i = 0; i < areas.Count; i++)
{
sqlQuery.Append("OR a.area_id = @d" + i.ToString() + " ");
}
sqlQuery.Append(")");