开发者

PredicateBuilder and nested predicates

开发者 https://www.devze.com 2022-12-12 03:34 出处:网络
I\'m trying to use the Predicate from Albahari to create a TSQL statement like: select * from channel where channel.VendorID IN (@vendorIDs)

I'm trying to use the Predicate from Albahari to create a TSQL statement like:

select * from channel
where channel.VendorID IN (@vendorIDs)
AND channel.FranchiseID IN (@franchiseIDs)

or a predicate like : c => (c.VendorID = x || c.VendorID == x2 ...) && (c.FranchiseID == f || c.FranchiseID == f2 ...)

but I'm having troubles. Here is my attempt:

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

My table has 60,000 rows, so going to the database and selecting them all, then filtering is not an o开发者_运维知识库ption. Channel is a LinqToSql entity. Also either the SelectedFranchises or the SelectedVendors can be empty, but not both at one time. EDIT: I need to distinct this list by the channel.Franchise.Name as well.. Maybe I should just use a stored procedure?

How would you do this?


To side step the whole predicate issue why not use the "Contains()" statement?

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

Alternatively, to use the predicate method, you wouldn't want to join them with an "or" because the two conditions are "and"'d in your example SQL statement. Instead, just run them consecutively through a where clause. I don't know how your SelectByPredicate function works, but you may be successful following the same pattern with it:

var myResults = Channel.SelectByPredicate(franchisePredicate);
myResults = myResults.SelectByPredicate(vendorPredicate);

var myResults = Channel.Where(franchisePredicate).Where(vendorPredicate);

Update From Discussion in Comments

If what you want is to only match on vendor id/franchise id if the workordersessiondata contains at least one of those ids, you'd use the following logic:

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


Well I just did this:

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

Maybe tho the cleanest of all versions...


Given the extensions:

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

You could do this:

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

精彩评论

暂无评论...
验证码 换一张
取 消