Linq to sql 谓词生成器和嵌套谓词
我试图使用来自的谓词创建一个TSQL语句,如:Linq to sql 谓词生成器和嵌套谓词,linq-to-sql,predicatebuilder,Linq To Sql,Predicatebuilder,我试图使用来自的谓词创建一个TSQL语句,如: select * from channel where channel.VendorID IN (@vendorIDs) AND channel.FranchiseID IN (@franchiseIDs) 或者像这样的谓词:c=>(c.VendorID=x | | c.VendorID==x2…&&(c.特许ID==f | | c.特许ID==f2…) 但是我有麻烦了。以下是我的尝试: var vendorPredicate = Pre
select * from channel
where channel.VendorID IN (@vendorIDs)
AND channel.FranchiseID IN (@franchiseIDs)
或者像这样的谓词:c=>(c.VendorID=x | | c.VendorID==x2…&&(c.特许ID==f | | c.特许ID==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);
var vendorPredicate=PredicateBuilder.False();
foreach(workOrderSessionData.SelectedVendors中的供应商)
{
int tempId=vendor.VendorID;
vendorPredicate=vendorPredicate.Or(c=>c.VendorID==tempId);
}
var predicate=PredicateBuilder.False();
foreach(workOrderSessionData中的特许经营权。选定特许经营权)
{
int tempId=特许经营权。特许经营权id;
特许经营谓词=特许经营谓词。或(c=>c.特许经营ID==tempId);
//不起作用。或(卖方或预测);
}
Channel.SelectByPredicate(谓词);
我的表有60000行,所以转到数据库并选择所有行,然后过滤不是一个选项。通道是一个LinqToSql实体。此外,所选特许经营权或所选供应商可以为空,但不能同时为空。
编辑:我还需要按channel.Francision.Name区分此列表。。也许我应该使用存储过程
您将如何做到这一点?为了回避整个谓词问题,为什么不使用“Contains()”语句 即 或者,要使用谓词方法,您不希望用“or”连接它们,因为在示例SQL语句中,这两个条件是“and”。相反,只需通过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));
List VendorIDs=workOrderSessionData.SelectedVendors.Select(sv=>
sv.VendorID).ToList();
列出特许经营ID=workOrderSessionData.selected特许经营.Select(sf=>
sf.特许经营id).ToList();
var myResults=通道;
如果(VendorIDs.Count>0)
myResults=myResults.Where(c=>VendorIDs.Contains(c.VendorID));
如果(ID.Count>0)
myResults=myResults.Where(c=>特许经营ID.Contains(c.特许经营ID));
我刚刚做到了:
var prope = outerWhere.ToString();
if (prope.Equals("f => True") == false || prope.Equals("f => False") == false)
query = query.Where(outerWhere);
可能是所有版本中最干净的…鉴于扩展:
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);
}
}
公共静态类谓词扩展
{
公共静态谓词Or(this谓词@this,谓词Or){
返回值=>@this(value)| |或(value);
}
公共静态谓词And(this谓词@this,谓词And){
返回值=>@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));
}
谓词vendorPredicate=c=>false;
foreach(workOrderSessionData.SelectedVendors中的var供应商)
{
int tempId=vendor.VendorID;
vendorPredicate=vendorPredicate.Or(c=>c.VendorID==tempId);
}
谓词c=>false;
foreach(workOrderSessionData中的var特许权。选定特许权)
{
int tempid=特许经营权。特许经营权id;
特许经营谓词=特许经营谓词。或(c=>c.特许经营ID==tempid);
}
var channelPredicate=vendorPredicate.和(Predicate);
var query=Channels.Where(c=>channelPredicate(c));
}
如果所选供应商为空或所选特许权为空(这是可能的),则第一个示例将失败。你会怎么处理?Sql Profilier中的where子句是“where 0=1”,是指返回0行还是抛出异常?这里的FAILES是指来自数据库的空结果。谢谢你的帮助,没问题。我询问的原因是,如果语句中的任何一个都失败了,那么您提供的SQL查询也不会返回任何结果,因为它说这两个ID必须在各自的列表中。这听起来像是你要求的,除非其中一个列表是空的,那么你只想匹配完整的列表。是吗?当其中一个列表为空时,我仍然需要根据填充的另一个列表进行筛选。因此,我需要获得供应商和特许经营权的所有渠道,或供应商的所有渠道,或特许经营权的所有渠道。
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));
}