嗨,谢谢你,
我正在尝试实现一个搜索功能,其中结果可以填充到Gridview。我正在使用LINQ在c#中查询我的数据库。
我想弄清楚的问题是,如果用户想要搜索具有多个搜索字词的多个列/字段,那么我该怎么做?因此,如果我搜索具有这3个字段的表并且我有一些数据,例如:
firstName | lastname | players#
- 迈克尔|乔丹| 12
- 迈克尔|乔丹| 24
- 迈克尔|乔丹| 45
- 德安德鲁|乔丹| 6
- 杰罗姆|乔丹| 44
- 约旦|火花| 88
醇>
现在,如果我搜索乔丹,我会得到一切:
如果我搜索迈克尔乔丹,我应该排第1,2,3行。
如果我搜索Jordan Sparks 88,那么我应该排第6。
所以我的问题是我不知道搜索词可能在表中的哪个位置,所以我必须搜索所有列/字段。在我当前的代码中,我有一些东西,我遍历每个列/字段名称并使用包含()然后|| (“或”),但它仅适用于1个搜索词。
是否有一种优雅而简单的方法来搜索和过滤整个linq表,以便最小化列表?从那里我将把结果添加到数据源然后绑定它。
@Sphinxxx我使用的是典型的gridview。它看起来像这样:
<asp:GridView ID="GridView" runat="server" AllowSorting="True" PagerStyle-Mode="NumericPages"
AutoGenerateColumns="false" Width="100%" CssClass="gridView" OnPageIndexChanging="GridView_PageIndexChanging"
AllowPaging="True" DataKeyNames="idPlayersList" OnRowCommand="GridView_RowCommand"
OnRowEditing="GridView_RowEditing" OnRowCancelingEdit="GridView_CancelEditRow"
OnRowUpdating="GridView_UpdateRow" OnRowDataBound="GridView_RowDataBound">
<RowStyle CssClass="rowStyle"></RowStyle>
<asp:BoundField DataField="FirstName" HeaderText="First Name" SortExpression="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="Last Name" SortExpression="LastName" />
<asp:BoundField DataField="PlayersNumber" HeaderText="Players Number" SortExpression="PlayersNumber" />
<asp:TemplateField HeaderText="Team" SortExpression="Team">
<EditItemTemplate>
<asp:DropDownList ID="ddlTeam" runat="server" CssClass="dropdown" AutoPostBack="True"
AppendDataBoundItems="true" DataTextField="TeamName" DataValueField="idTeam">
</asp:DropDownList>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="lblTeam" runat="server" Text='<%# Bind("TeamName") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
我当前的搜索功能如下所示:
/**
* This method is for button search functionality
*
*/
protected void btnSearch_Click(object sender, EventArgs e)
{
// Call to Entity Model Framework
DBModel.DBEntities context = new DBModel.DBEntities();
string[] searchTerms = txtSearch.Text.Trim().Split('&');
//Prepare to build a "players" query:
IQueryable<DBModel.playersList> playersListQuery = context.playersLists;
foreach (var term in searchTerms)
{
//Refine our query, one search term at a time:
playersListQuery = playersListQuery.Where(p => p.isDeleted == false && (p.FirstName.Contains(term.Trim()) ||
p.LastName.Contains(term.Trim()) ||
p.PlayersNumber.Contains(term.Trim()) ||
p.Team.Name.Contains(term.Trim())));
}
//Now we have the complete query. Get the results from the database:
var filteredplayersList = playersListQuery.Select(s => new
{
idPlayersList = s.idPlayersList,
FirstName = s.FirstName,
LastName = s.LastName,
PlayersNumber = s.PlayersNumber,
TeamName = s.Team.Name
}).ToList();
GridView.DataSource = filteredplayersList; //Connecting query to the datasource Gridview
GridView.DataBind(); //Binding Gridview
}
答案 0 :(得分:6)
幸运的是,在Linq2SQL中创建多个AND(每个搜索词一个)很容易 - 只需继续向查询添加.Where(..
:
string[] searchTerms = "Jordan Sparks 88".Split(' ');
using (var dc = new MyDataContext())
{
//Using DataContext.Log is handy
//if we want to look at Linq2SQL's generated SQL:
dc.Log = new System.IO.StringWriter();
//Prepare to build a "players" query:
IQueryable<Player> playersQuery = dc.Players;
//Refine our query, one search term at a time:
foreach (var term in searchTerms)
{
//Create (and use) a local variable of the search term
//to avoid the "outer variable trap":
//http://stackoverflow.com/questions/3416758
//http://stackoverflow.com/questions/295593
var currentTerm = term.Trim();
playersQuery = playersQuery.Where(p => (p.isDeleted == false)
&&
(p.FirstName.Contains(currentTerm) ||
p.LastName.Contains(currentTerm) ||
p.PlayersNumber.Contains(currentTerm) ||
p.Team.Name.Contains(currentTerm))
);
}
//Now we have the complete query. Get the results from the database:
var filteredPlayers = playersQuery.Select(p => new
{
p.idPlayer,
p.FirstName,
p.LastName,
p.PlayersNumber,
TeamName = p.Team.Name
})
.ToArray();
//See if the generated SQL looked like it was supposed to:
var sql = dc.Log.ToString();
}
答案 1 :(得分:0)
如果只需要对所有属性使用Contains条件,则可以将所有需要的属性封装到一个属性中,然后可以使用较少字段的LINQ表达式,看起来会更干净
public class Player
{
public string SearchField { get => string.Format("{0}{1}{2}{3}",FirstName,LastName,PlayersNumber,Team); }
public string FirstName {get; set;}
public string LastName {get; set;}
public string PlayersNumber {get; set;}
public string Team {get; set;}
}
更好的是,我建议您在创建对象实例时在构造函数中设置SearchField,这样可以提高性能,避免为每次调用创建子字符串。
public string SearchField { get; private set; }
public Player(string firstName, string lastName, playersNumber, string team)
{
FirstName = firstName;
LastName = lastName;
PlayersNumber = playersNumber;
Team = team;
SearchField = string.Format("{0}{1}{2}{3}",firstName,lastName,playersNumber,team);
}
然后您只需按 SearchField 属性进行过滤
foreach (var term in searchTerms)
{
var currentTerm = term.Trim();
playersQuery = playersQuery.Where(p => p.isDeleted == false &&
p.SearchField.Contains(currentTerm));
}
现在,您有了一个具有更少字段的LINQ表达式,这使您获得了完全相同的结果集。
我刚刚看到您提到您正在使用LINQ to SQL查询,您可以通过在SQL表中创建连接值的 Computed Column 来应用相同的方法从多列开始,您可以从SQL Server 2012开始执行此操作。
希望有人发现此解决方案有帮助。
致谢!