LINQ PredicateBuilder 在我的动态搜索中不起作用
LINQ PredicateBuilder not work in my dynamic search
我的数据库中有一本书 table,我的 edmx 中有一个名为 vwShared 的图书视图。我想使用运算符创建动态搜索供用户查找书籍。我有 2 个 SearchColumns 下拉列表包含 "Title, Authors, Published Year, Subject"。我有 2 个 SearchType 下拉列表包含 "StartsWith, Contains, EndsWith, Equals"。我有另一个下拉列表包含 "AND, OR" 以组合 2 个搜索结果。以下是我的代码。
var predicate = PredicateBuilder.True<DataLayer.vwShared>();
if (joinOperator == "AND")
{
if (SearchColumn1 == "Title" && SearchType1 == "Contains")
predicate = predicate.And(e1 => e1.Title.Contains(txtSearch1.Text));
if (SearchColumn2 == "Authors" && SearchType2 == "Contains")
predicate = predicate.And(e1 => e1.Authors.Contains(txtSearch2.Text));
}
else if (joinOperator == "OR")
{
if (SearchColumn1 == "Title" && SearchType1 == "Contains")
predicate = predicate.Or(e1 => e1.Title.Contains(txtSearch1.Text));
if (SearchColumn2 == "Authors" && SearchType2 == "Contains")
predicate = predicate.Or(e1 => e1.Authors.Contains(txtSearch2.Text));
}
List<DataLayer.vwShared> bookList= new DataLayer.Solib_DMREntities().SP_SharedData_GetAll("AllLocal").ToList<DataLayer.vwShared>();
var bookList= from books in bookList.AsQueryable().Where(predicate)
select books ;
gvBooks.DataSource = bookList.ToList();
gvBooks.DataBind();
以上代码不是 return 正确的结果。有什么不对。 ?
以下是我的参考网站。
http://www.albahari.com/nutshell/predicatebuilder.aspx
请多多指教
谢谢。
步1:Model
public class Person
{
public int PersonId { get; set; }
public int? Age { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int? Salary { get; set; }
}
public class PersonDBContext : DbContext
{
public virtual DbSet<Person> People { get; set; }
}
第 2 步:控制器
public class PersonController
{
PersonDBContext db = new PersonDBContext();
public void Add(Person person)
{
db.People.Add(person);
db.SaveChanges();
}
public List<Person> GetAll()
{
return db.People.ToList();
}
public List<Person> GetByPredicateValue(Expression<Func<Person, bool>> predicate)
{
if (predicate != null)
return db.People.Where(predicate.Compile()).ToList();
else
return null;
}
public List<Person> GetByPredicateAndPersonListValue(List<Person> PeopleList,Expression<Func<Person, bool>> predicate)
{
if (predicate != null)
return PeopleList.Where(predicate.Compile()).ToList();
else
return null;
}
}
第 3 步:隐藏代码
public partial class MainWindow : Window
{
PersonController pc;
public static List<Person> PeopleFilterList = null;
public static string CurrentColumn = null;
public MainWindow()
{
pc = new PersonController();
InitializeComponent();
grid.ItemsSource = pc.GetAll();
grid.PreviewMouseDown += grid_PreviewMouseDown;
}
void grid_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
TableViewHitInfo hi = ((TableView)grid.View).CalcHitInfo(e.OriginalSource as DependencyObject);
if (hi == null) return;
if (hi.HitTest == TableViewHitTest.ColumnHeader || hi.HitTest == TableViewHitTest.ColumnHeaderFilterButton)
{
grid.UnselectAll();
GridColumn currentColumn = ((DevExpress.Xpf.Grid.GridViewHitInfoBase)(hi)).Column;
CurrentColumn = currentColumn.FieldName;
(grid.View as TableView).SelectCells(0, currentColumn, grid.VisibleRowCount - 1, currentColumn);
}
}
Expression<Func<Person, bool>> _result=null;
string str="";
private void IdForm_ButtonClicked(object sender, IdentityUpdateEventArgs e)
{
_result = e.FirstName;
}
public MainWindow(Expression<Func<Person, bool>> result)
{
Window1 f = new Window1();
f.IdentityUpdated += new Window1.IdentityUpdateHandler(IdForm_ButtonClicked);
pc = new PersonController();
InitializeComponent();
_result = result;
if (PeopleFilterList != null)
PeopleFilterList = pc.GetByPredicateAndPersonListValue(PeopleFilterList,_result).ToList();
else
PeopleFilterList = pc.GetByPredicateValue(_result).ToList();
grid.ItemsSource = PeopleFilterList;
grid.PreviewMouseDown += grid_PreviewMouseDown;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Window1 w1 = new Window1(CurrentColumn);
w1.Show();
}
}
第 4 步:过滤后面的代码
public partial class Window1 : Window
{
public delegate void IdentityUpdateHandler(object sender, IdentityUpdateEventArgs e);
public event IdentityUpdateHandler IdentityUpdated;
string _currentColumn = null;
public Window1()
{
InitializeComponent();
}
public Window1(string currentColumn)
{
_currentColumn = currentColumn;
InitializeComponent();
}
public static Expression<Func<Person, bool>> predicateValue;
IdentityUpdateEventArgs args;
private void Button_Click(object sender, RoutedEventArgs e)
{
string operatorName = "";
if (!String.IsNullOrEmpty(txtSmaller.Text.Trim()))
operatorName = txtSmaller.Name;
else if (!String.IsNullOrEmpty(txtElder.Text.Trim()))
operatorName = txtElder.Name;
else if (!String.IsNullOrEmpty(txtContains.Text.Trim()))
operatorName = txtContains.Name;
else if (!String.IsNullOrEmpty(txtStartWith.Text.Trim()))
operatorName = txtStartWith.Name;
else if (!String.IsNullOrEmpty(txtEqual.Text.Trim()))
operatorName = txtEqual.Name;
else if (!String.IsNullOrEmpty(txtNotEqual.Text.Trim()))
operatorName = txtNotEqual.Name;
else if (!String.IsNullOrEmpty(txtSmallerOrEqual.Text.Trim()))
operatorName = txtSmallerOrEqual.Name;
else if (!String.IsNullOrEmpty(txtElderOrEqual.Text.Trim()))
operatorName = txtElderOrEqual.Name;
else if (!String.IsNullOrEmpty(txtSmallerThan.Text.Trim()) && !String.IsNullOrEmpty(txtBiggerThan.Text.Trim()))
operatorName = txtSmallerThan.Name;
switch (operatorName)
{
case "txtSmaller":
predicateValue = (x => (int)x.GetType().GetProperty(_currentColumn).GetValue(x, null) < Convert.ToInt32(txtSmaller.Text));
break;
case "txtElder":
predicateValue = (x => (int)x.GetType().GetProperty(_currentColumn).GetValue(x, null) > Convert.ToInt32(txtElder.Text));
break;
case "txtSmallerOrEqual":
predicateValue = (x => (int)x.GetType().GetProperty(_currentColumn).GetValue(x, null) <= Convert.ToInt32(txtSmallerOrEqual.Text));
break;
case "txtElderOrEqual":
predicateValue = (x => (int)x.GetType().GetProperty(_currentColumn).GetValue(x, null) >= Convert.ToInt32(txtElderOrEqual.Text));
break;
case "txtEqual":
predicateValue = (x => (int)x.GetType().GetProperty(_currentColumn).GetValue(x, null) == Convert.ToInt32(txtEqual.Text));
break;
case "txtNotEqual":
predicateValue = (x => (int)x.GetType().GetProperty(_currentColumn).GetValue(x, null) != Convert.ToInt32(txtNotEqual.Text));
break;
case "txtSmallerThan":
predicateValue = (x => (int)x.GetType().GetProperty(_currentColumn).GetValue(x, null) >= Convert.ToInt32(txtBiggerThan.Text)
&& (int)x.GetType().GetProperty(_currentColumn).GetValue(x, null) <= Convert.ToInt32(txtSmallerThan.Text));
break;
case "txtStartWith":
predicateValue = (x => x.GetType().GetProperty(_currentColumn).GetValue(x, null).ToString().StartsWith(txtStartWith.Text));
break;
case "txtContains":
predicateValue = (x => x.GetType().GetProperty(_currentColumn).GetValue(x,null).ToString().Contains(txtContains.Text));
break;
}
MainWindow mw = new MainWindow(predicateValue);
mw.Show();
this.Close();
}
void Window1_IdentityUpdated(object sender, IdentityUpdateEventArgs e)
{
e = args;
}
}
public class IdentityUpdateEventArgs : System.EventArgs
{
private Expression<Func<Person, bool>> mFirstName;
public IdentityUpdateEventArgs(Expression<Func<Person, bool>> sFirstName)
{
this.mFirstName = sFirstName;
}
public Expression<Func<Person, bool>> FirstName
{
get
{
return mFirstName;
}
}
}
回答你的具体问题。问题出在构建OR
predicate 的分支,在这种情况下你应该从PredicateBuilder.False
开始,否则根本不会过滤(我们从学校知道,true or something
是总是 true
:)
// ...
else if (joinOperator == "OR")
{
predicate = PredicateBuilder.False<DataLayer.vwShared>();
// ...
}
// ...
我的数据库中有一本书 table,我的 edmx 中有一个名为 vwShared 的图书视图。我想使用运算符创建动态搜索供用户查找书籍。我有 2 个 SearchColumns 下拉列表包含 "Title, Authors, Published Year, Subject"。我有 2 个 SearchType 下拉列表包含 "StartsWith, Contains, EndsWith, Equals"。我有另一个下拉列表包含 "AND, OR" 以组合 2 个搜索结果。以下是我的代码。
var predicate = PredicateBuilder.True<DataLayer.vwShared>();
if (joinOperator == "AND")
{
if (SearchColumn1 == "Title" && SearchType1 == "Contains")
predicate = predicate.And(e1 => e1.Title.Contains(txtSearch1.Text));
if (SearchColumn2 == "Authors" && SearchType2 == "Contains")
predicate = predicate.And(e1 => e1.Authors.Contains(txtSearch2.Text));
}
else if (joinOperator == "OR")
{
if (SearchColumn1 == "Title" && SearchType1 == "Contains")
predicate = predicate.Or(e1 => e1.Title.Contains(txtSearch1.Text));
if (SearchColumn2 == "Authors" && SearchType2 == "Contains")
predicate = predicate.Or(e1 => e1.Authors.Contains(txtSearch2.Text));
}
List<DataLayer.vwShared> bookList= new DataLayer.Solib_DMREntities().SP_SharedData_GetAll("AllLocal").ToList<DataLayer.vwShared>();
var bookList= from books in bookList.AsQueryable().Where(predicate)
select books ;
gvBooks.DataSource = bookList.ToList();
gvBooks.DataBind();
以上代码不是 return 正确的结果。有什么不对。 ? 以下是我的参考网站。 http://www.albahari.com/nutshell/predicatebuilder.aspx 请多多指教
谢谢。
步1:Model
public class Person
{
public int PersonId { get; set; }
public int? Age { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int? Salary { get; set; }
}
public class PersonDBContext : DbContext
{
public virtual DbSet<Person> People { get; set; }
}
第 2 步:控制器
public class PersonController
{
PersonDBContext db = new PersonDBContext();
public void Add(Person person)
{
db.People.Add(person);
db.SaveChanges();
}
public List<Person> GetAll()
{
return db.People.ToList();
}
public List<Person> GetByPredicateValue(Expression<Func<Person, bool>> predicate)
{
if (predicate != null)
return db.People.Where(predicate.Compile()).ToList();
else
return null;
}
public List<Person> GetByPredicateAndPersonListValue(List<Person> PeopleList,Expression<Func<Person, bool>> predicate)
{
if (predicate != null)
return PeopleList.Where(predicate.Compile()).ToList();
else
return null;
}
}
第 3 步:隐藏代码
public partial class MainWindow : Window
{
PersonController pc;
public static List<Person> PeopleFilterList = null;
public static string CurrentColumn = null;
public MainWindow()
{
pc = new PersonController();
InitializeComponent();
grid.ItemsSource = pc.GetAll();
grid.PreviewMouseDown += grid_PreviewMouseDown;
}
void grid_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
TableViewHitInfo hi = ((TableView)grid.View).CalcHitInfo(e.OriginalSource as DependencyObject);
if (hi == null) return;
if (hi.HitTest == TableViewHitTest.ColumnHeader || hi.HitTest == TableViewHitTest.ColumnHeaderFilterButton)
{
grid.UnselectAll();
GridColumn currentColumn = ((DevExpress.Xpf.Grid.GridViewHitInfoBase)(hi)).Column;
CurrentColumn = currentColumn.FieldName;
(grid.View as TableView).SelectCells(0, currentColumn, grid.VisibleRowCount - 1, currentColumn);
}
}
Expression<Func<Person, bool>> _result=null;
string str="";
private void IdForm_ButtonClicked(object sender, IdentityUpdateEventArgs e)
{
_result = e.FirstName;
}
public MainWindow(Expression<Func<Person, bool>> result)
{
Window1 f = new Window1();
f.IdentityUpdated += new Window1.IdentityUpdateHandler(IdForm_ButtonClicked);
pc = new PersonController();
InitializeComponent();
_result = result;
if (PeopleFilterList != null)
PeopleFilterList = pc.GetByPredicateAndPersonListValue(PeopleFilterList,_result).ToList();
else
PeopleFilterList = pc.GetByPredicateValue(_result).ToList();
grid.ItemsSource = PeopleFilterList;
grid.PreviewMouseDown += grid_PreviewMouseDown;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Window1 w1 = new Window1(CurrentColumn);
w1.Show();
}
}
第 4 步:过滤后面的代码
public partial class Window1 : Window
{
public delegate void IdentityUpdateHandler(object sender, IdentityUpdateEventArgs e);
public event IdentityUpdateHandler IdentityUpdated;
string _currentColumn = null;
public Window1()
{
InitializeComponent();
}
public Window1(string currentColumn)
{
_currentColumn = currentColumn;
InitializeComponent();
}
public static Expression<Func<Person, bool>> predicateValue;
IdentityUpdateEventArgs args;
private void Button_Click(object sender, RoutedEventArgs e)
{
string operatorName = "";
if (!String.IsNullOrEmpty(txtSmaller.Text.Trim()))
operatorName = txtSmaller.Name;
else if (!String.IsNullOrEmpty(txtElder.Text.Trim()))
operatorName = txtElder.Name;
else if (!String.IsNullOrEmpty(txtContains.Text.Trim()))
operatorName = txtContains.Name;
else if (!String.IsNullOrEmpty(txtStartWith.Text.Trim()))
operatorName = txtStartWith.Name;
else if (!String.IsNullOrEmpty(txtEqual.Text.Trim()))
operatorName = txtEqual.Name;
else if (!String.IsNullOrEmpty(txtNotEqual.Text.Trim()))
operatorName = txtNotEqual.Name;
else if (!String.IsNullOrEmpty(txtSmallerOrEqual.Text.Trim()))
operatorName = txtSmallerOrEqual.Name;
else if (!String.IsNullOrEmpty(txtElderOrEqual.Text.Trim()))
operatorName = txtElderOrEqual.Name;
else if (!String.IsNullOrEmpty(txtSmallerThan.Text.Trim()) && !String.IsNullOrEmpty(txtBiggerThan.Text.Trim()))
operatorName = txtSmallerThan.Name;
switch (operatorName)
{
case "txtSmaller":
predicateValue = (x => (int)x.GetType().GetProperty(_currentColumn).GetValue(x, null) < Convert.ToInt32(txtSmaller.Text));
break;
case "txtElder":
predicateValue = (x => (int)x.GetType().GetProperty(_currentColumn).GetValue(x, null) > Convert.ToInt32(txtElder.Text));
break;
case "txtSmallerOrEqual":
predicateValue = (x => (int)x.GetType().GetProperty(_currentColumn).GetValue(x, null) <= Convert.ToInt32(txtSmallerOrEqual.Text));
break;
case "txtElderOrEqual":
predicateValue = (x => (int)x.GetType().GetProperty(_currentColumn).GetValue(x, null) >= Convert.ToInt32(txtElderOrEqual.Text));
break;
case "txtEqual":
predicateValue = (x => (int)x.GetType().GetProperty(_currentColumn).GetValue(x, null) == Convert.ToInt32(txtEqual.Text));
break;
case "txtNotEqual":
predicateValue = (x => (int)x.GetType().GetProperty(_currentColumn).GetValue(x, null) != Convert.ToInt32(txtNotEqual.Text));
break;
case "txtSmallerThan":
predicateValue = (x => (int)x.GetType().GetProperty(_currentColumn).GetValue(x, null) >= Convert.ToInt32(txtBiggerThan.Text)
&& (int)x.GetType().GetProperty(_currentColumn).GetValue(x, null) <= Convert.ToInt32(txtSmallerThan.Text));
break;
case "txtStartWith":
predicateValue = (x => x.GetType().GetProperty(_currentColumn).GetValue(x, null).ToString().StartsWith(txtStartWith.Text));
break;
case "txtContains":
predicateValue = (x => x.GetType().GetProperty(_currentColumn).GetValue(x,null).ToString().Contains(txtContains.Text));
break;
}
MainWindow mw = new MainWindow(predicateValue);
mw.Show();
this.Close();
}
void Window1_IdentityUpdated(object sender, IdentityUpdateEventArgs e)
{
e = args;
}
}
public class IdentityUpdateEventArgs : System.EventArgs
{
private Expression<Func<Person, bool>> mFirstName;
public IdentityUpdateEventArgs(Expression<Func<Person, bool>> sFirstName)
{
this.mFirstName = sFirstName;
}
public Expression<Func<Person, bool>> FirstName
{
get
{
return mFirstName;
}
}
}
回答你的具体问题。问题出在构建OR
predicate 的分支,在这种情况下你应该从PredicateBuilder.False
开始,否则根本不会过滤(我们从学校知道,true or something
是总是 true
:)
// ...
else if (joinOperator == "OR")
{
predicate = PredicateBuilder.False<DataLayer.vwShared>();
// ...
}
// ...