如何使用实体框架SqlQuery保护SQL参数?

时间:2014-10-01 20:27:45

标签: c# asp.net .net sql-server entity-framework

我有这种方法应该采用未知数量的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();
        }
    }

我知道它内置了这个功能,但正如我之前所述,我不知道将会出现的确切数量

db.Database.SqlQuery<LocationModel>("SELECT * FROM table WHERE id = @p0 ;", id).ToList();

由于

2 个答案:

答案 0 :(得分:3)

为什么不使用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(")");

答案 1 :(得分:3)

虽然我完全同意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,或至少可以轻易获得数量。