Linq to sql 谓词生成器和嵌套谓词

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

我试图使用来自的谓词创建一个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 = 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));
}