C# 如何将多个查询与EntityFramework相交以进行搜索?
当人们搜索我的网站时,我不想只搜索值(q),我想用空格作为分隔符搜索每个单词。我编写了大部分代码,但有些部分我不知道怎么做 你能检查一下下面代码中的“待办事项”并给我一个建议吗?或者完全不同的方法。顺便说一下,如果可能的话,我想保留SQL代码部分,因为这对我来说更自然,但所有的TODO都可以在LINQ中完成 谢谢 代码如下:C# 如何将多个查询与EntityFramework相交以进行搜索?,c#,asp.net-mvc,linq,search,entity-framework-4,C#,Asp.net Mvc,Linq,Search,Entity Framework 4,当人们搜索我的网站时,我不想只搜索值(q),我想用空格作为分隔符搜索每个单词。我编写了大部分代码,但有些部分我不知道怎么做 你能检查一下下面代码中的“待办事项”并给我一个建议吗?或者完全不同的方法。顺便说一下,如果可能的话,我想保留SQL代码部分,因为这对我来说更自然,但所有的TODO都可以在LINQ中完成 谢谢 代码如下: [HttpPost] public ActionResult Search(string q) { ViewBag.
[HttpPost]
public ActionResult Search(string q)
{
ViewBag.q = q;
String[] strQueries = q.Split(' ');
//TODO: Create an array of type var???
foreach (string str in strQueries)
{
var recipesTemp = db.Recipes.SqlQuery(
String.Format(
"SELECT * FROM Recipe WHERE Name LIKE '%{0}%' " +
"UNION ALL " +
"SELECT * FROM Recipe WHERE IDRecipe IN ( " +
" SELECT IDRecipe FROM Subtitle WHERE Name LIKE '%{0}%') " +
"UNION ALL " +
"SELECT * FROM Recipe WHERE IDRecipe IN ( " +
" SELECT IDRecipe FROM RecipeTag " +
" INNER JOIN Tag ON Tag.IDTag = RecipeTag.IDTag " +
" WHERE Name LIKE '%{0}%') " +
"UNION ALL " +
"SELECT * FROM Recipe WHERE IDRecipe IN ( " +
" SELECT IDRecipe FROM Subtitle " +
" INNER JOIN Ingredient ON Ingredient.IDSubtitle = Subtitle.IDSubtitle " +
" WHERE QuantityAndName LIKE '%{0}%')", str)).Distinct().OrderBy(r => r.Name).ToList();
//TODO: Add recipesTemp to the array of var
}
var recipes = //TODO: INTERSECT the results from all the recipesTemp in the array of type var
return View("Search", recipes);
}
以下代码将完成此操作:
var selectedRecipies = new List<IEnumerable<Recipy>>();
foreach(...)
{
...
selectedRecipies.Add(recipesTemp);
}
var recipies = selectedRecipies.Aggregate((a, i) => a.Intersect(i));
var selectedRecipies=new List();
foreach(…)
{
...
选择配方。添加(配方温度);
}
var recipies=所选的详细信息聚合((a,i)=>a.Intersect(i));
此外,在您的位置上,我还将考虑@KirkWoll的注释,并使用FullTextSearch而不是LIKEs。对于
strquerys
中的每个str
,您将创建一个按名称排序并存储在列表中的不同格式的SQL查询,其中T
是一个Recipe
(?)。试试这样:
var allRecipes = strQueries.Select(str => db.Recipes.SqlQuery(
String.Format(
"SELECT * FROM Recipe WHERE Name LIKE '%{0}%' " +
"UNION ALL " +
"SELECT * FROM Recipe WHERE IDRecipe IN ( " +
" SELECT IDRecipe FROM Subtitle WHERE Name LIKE '%{0}%') " +
"UNION ALL " +
"SELECT * FROM Recipe WHERE IDRecipe IN ( " +
" SELECT IDRecipe FROM RecipeTag " +
" INNER JOIN Tag ON Tag.IDTag = RecipeTag.IDTag " +
" WHERE Name LIKE '%{0}%') " +
"UNION ALL " +
"SELECT * FROM Recipe WHERE IDRecipe IN ( " +
" SELECT IDRecipe FROM Subtitle " +
" INNER JOIN Ingredient ON Ingredient.IDSubtitle = Subtitle.IDSubtitle " +
" WHERE QuantityAndName LIKE '%{0}%')", str)).Distinct().OrderBy(recipe => recipe.Name))
.SelectMany(recipe => recipe);
之后,所有配方
应按类型IEnumerable
分类 尝试这种方法,它将生成一条SQL语句:
var names = q.Split(' ');
if(names.Any())
{
var firstName = names[0];
var query = context.Recipes.Where (q => q.Name.Contains(firstName));
// other unions ...
// query = query.Union( context.Recipes.Where (...
foreach (var name in names.Skip(1))
{
query = query.Union(context.Recipes.Where (q => q.Name.Contains(name)));
// other unions ...
// query = query.Union( context.Recipes.Where (...
}
// query evaluated now
var recipes = query.ToList();
}
如果这里有一个“配方”,那就是SQL注入攻击。除了安全问题之外,你对如何做到这一点有什么想法吗?在这种情况下,您建议如何避免SQL注入攻击?我不确定,但我认为使用您的方法,第一个名称将仅在配方名称中搜索,而另一个名称将在所有其他位置(标签、配料等)搜索。我想在这4个地方搜索拆分中的所有名称。但我理解你答案背后的想法,并将在今晚尝试实现它。我知道什么是FullTextSearch(例如Lucene),但我一直认为它是在大量文本中搜索。在我的例子中,我只搜索4个非常小的表(长度为50的varchar)。FullTextSearch与此匹配吗?是的,MSSQL中有一个“内置”FullTextSearch功能,因此您不必安装Lucene。尽管如此,它会在大量文本或Synomins的搜索中显示出来,因此您可能会暂时忘记它,因为它实际上会成为您的一个问题。请注意,我使用您的技术,并将查询中SQL中的部分翻译为linq,以避免SQL注入!非常感谢:)