我正在尝试使用Albahari中的谓词创建一个TSQL语句,如:
select * from channel
where channel.VendorID IN (@vendorIDs)
AND channel.FranchiseID IN (@franchiseIDs)
或类似谓词:c => (c.VendorID = x || c.VendorID == x2 ...)&& (c.FranchiseID == f || c.FranchiseID == f2 ...)
但是我遇到了麻烦。这是我的尝试: var vendorPredicate = PredicateBuilder.False<Channel>();
foreach (Vendor vendor in workOrderSessionData.SelectedVendors)
{
int tempId = vendor.VendorID;
vendorPredicate = vendorPredicate.Or(c => c.VendorID == tempId);
}
var franchisePredicate = PredicateBuilder.False<Channel>();
foreach (Franchise franchise in workOrderSessionData.SelectedFranchises)
{
int tempId = franchise.FranchiseID;
franchisePredicate = franchisePredicate.Or(c => c.FranchiseID == tempId);
// doesn't work franchisePredicate.Or(vendorPredicate);
}
Channel.SelectByPredicate(franchisePredicate);
我的表有60,000行,所以进入数据库并选择所有行,然后过滤不是一个选项。 Channel是LinqToSql实体。 SelectedFranchises或SelectedVendors也可以为空,但不能同时为空。 编辑:我需要通过channel.Franchise.Name来区分这个列表..也许我应该只使用存储过程?
你会怎么做?
答案 0 :(得分:2)
为了不使用“Contains()”语句,为了解决整个谓词问题?
IE
var myResults =
from c in Channel
where
workOrderSessionData.SelectedVendors.Select(sv =>
sv.VendorID).Contains(c.VendorID)
&& workOrderSessionData.SelectedFranchises.Select(sf =>
sf.FranchiseID).Contains(c.FranchiseID)
select c;
Channel.SelectByPredicate(franchisePredicate);
或者,要使用谓词方法,您不希望将它们与“或”连接,因为在示例SQL语句中这两个条件是“和”。相反,只需通过where子句连续运行它们。我不知道你的SelectByPredicate函数是如何工作的,但你可能会成功地遵循相同的模式:
var myResults = Channel.SelectByPredicate(franchisePredicate);
myResults = myResults.SelectByPredicate(vendorPredicate);
var myResults = Channel.Where(franchisePredicate).Where(vendorPredicate);
从评论中的讨论更新
如果workordersessiondata至少包含其中一个id,那么你想要的只是匹配供应商ID /特许经营ID,你将使用以下逻辑:
List<int> VendorIDs = workOrderSessionData.SelectedVendors.Select(sv =>
sv.VendorID).ToList();
List<int> FranchiseIDs = workOrderSessionData.SelectedFranchises.Select(sf =>
sf.FranchiseID).ToList();
var myResults = Channel;
if(VendorIDs.Count > 0)
myResults = MyResults.Where(c => VendorIDs.Contains(c.VendorID));
if(FranchiseIDs.Count > 0)
myResults = MyResults.Where(c => FranchiseIDs.Contains(c.FranchiseID));
答案 1 :(得分:0)
我刚刚做了这个:
var prope = outerWhere.ToString();
if (prope.Equals("f => True") == false || prope.Equals("f => False") == false)
query = query.Where(outerWhere);
也许是所有版本中最干净的......
答案 2 :(得分:0)
鉴于扩展名:
public static class PredicateExtensions
{
public static Predicate<T> Or<T>(this Predicate<T> @this, Predicate<T> or) {
return value => @this(value) || or(value);
}
public static Predicate<T> And<T>(this Predicate<T> @this, Predicate<T> and) {
return value => @this(value) && and(value);
}
}
你可以这样做:
Predicate<Channel> vendorPredicate = c => false;
foreach (var vendor in workOrderSessionData.SelectedVendors)
{
int tempId = vendor.VendorID;
vendorPredicate = vendorPredicate.Or(c => c.VendorID == tempId);
}
Predicate<Channel> franchisePredicate = c => false;
foreach (var franchise in workOrderSessionData.SelectedFranchises)
{
int tempid = franchise.FranchiseID;
franchisePredicate = franchisePredicate.Or(c => c.FranchiseID == tempid);
}
var channelPredicate = vendorPredicate.And(franchisePredicate);
var query = Channels.Where (c => channelPredicate(c));
}