1

我正在尝试使用来自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 来区分这个列表。也许我应该只使用存储过程?

你会怎么做?

4

3 回答 3

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);

从评论中的讨论更新

如果您想要的只是匹配供应商 ID/特许经营 ID(如果 workordersessiondata 至少包含这些 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));
于 2009-11-19T17:38:26.873 回答
0

好吧,我只是这样做了:

var prope = outerWhere.ToString();
if (prope.Equals("f => True") == false || prope.Equals("f => False") == false)
  query = query.Where(outerWhere);

也许是所有版本中最干净的......

于 2010-07-23T09:38:09.977 回答
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));
}
于 2012-04-10T08:13:48.653 回答