2012-02-27 54 views
0

我是lambda表达式的新手,我在试图弄清楚如何在一个表示我的实体框架查询时遇到问题。我也可能是错的,只有更好的方法去做我想做的事。如果这是真的,请让我知道。我的方案是我有一个高级搜索屏幕,您可以选择搜索名称,客户号码或电话号码。如果你愿意,你可以搜索超过1个。我使用实体框架作为我的后端,并为我的表设置了存储库。下面是我想使用lambda表达式问题

Func<Parties, bool> exp; 

exp = null; 

if (vm.CustomerNumberCriteria != null) 
{ 
    custID = Convert.ToInt32(vm.CustomerNumberCriteria); 
    exp = o => o.ID == custID; 
} 


if (vm.NameCriteria != null) 

    exp += o => o.LastName.Contains(vm.NameCriteria) || o.FirstName.Contains(vm.NameCriteria) || o.MiddleName.Contains(vm.NameCriteria) || o.Designation.Contains(vm.NameCriteria); 

if (vm.PhoneNumberCriteria != null) 

    exp += o => o.CentralPhoneNumbers.Any(child => child.PhoneNumber == vm.PhoneNumberCriteria); 

//TODO set tempresults 
tempresults = custs.All.Where(exp).ToList(); 

我的问题的代码似乎看待这个像一个和我需要的结果,如果有任何的搜索条件匹配。

谢谢

回答

3

这里有两个大问题。首先,您使用的是代表,而不是表达式树 - 这意味着您的整个表将被拉回客户端并在那里过滤。你想要Expression<Func<Parties, bool>>。现在

,如果你想建立“或”表达式树,最简单的方法是使用PredicateBuilder

var predicate = PredicateBuilder.False<Parties>(); 

if (vm.CustomerNumberCriteria != null) 
{ 
    custID = Convert.ToInt32(vm.CustomerNumberCriteria); 
    predicate = predicate.Or(o => o.ID == custID); 
} 

if (vm.NameCriteria != null) 
{ 
    custID = Convert.ToInt32(vm.CustomerNumberCriteria); 
    predicate = predicate.Or(o => o.LastName.Contains(vm.NameCriteria) /* etc */) 
} 

if (vm.PhoneNumberCriteria != null) 
{ 
    predicate = predicate.Or(o => o.CentralPhoneNumbers.Any 
        (child => child.PhoneNumber == vm.PhoneNumberCriteria)); 
} 

tempresults = custs.All.Where(predicate).ToList(); 
+0

'表达<缔约方,布尔>'应该是'表达>',对吗? – hvd 2012-02-27 17:44:20

+0

@ hvd:对,错字,对不起。固定。 – 2012-02-27 17:45:44

+0

对于anyoen看这个答案,你必须下载LinqKit来获得PredicateBuilder。通过Nuget很容易做到。您的解决方案对我来说非常棒。我必须改变你的例子的唯一的东西是最后一行,我不得不说custsA.AsExpandable.Where,但我认为,因为我的数据来自实体框架。 – 2012-02-28 14:53:13