Pinwheeler
Pinwheeler

Reputation: 113

IEnumerable.except error

I have two IEnumerable<dynamic> of data retrieved from database tables, called FullSet and InScopeSubSet .

The second IEnumerable<dynamic> is a subset of the first set (both sets have ChildID as their unique ID)

I would like to create a new IEnumerable<dynamic> that contains only items from x that do not occur in y

I have tried the following but it will not compile. It says: "extension methods cannot be dynamically dispatched. Consider casting the dynamic arguments or calling the extension method without the extension method syntax"

 var sql = "SELECT ChildID, FirstName, Surname FROM Child ORDER BY ChildID ASC";
 var FullSet =  DB.Query(sql);

 sql = "
 SELECT UserScope.ChildID, Child.FirstName, Child.Surname 
 FROM UserScope 
 INNER JOIN Child ON UserScope.ChildID=Child.ChildID 
 WHERE UserAccountID = @0 ORDER BY ChildID ASC
    ";
 var InScopeSubSet = DB.Query(sql, UserAccount.UserAccountID);

 var OutScopeSubSet  = FullSet .Except(InScopeSubSet );

Upvotes: 1

Views: 300

Answers (2)

phoog
phoog

Reputation: 43036

To resolve the compiler error, use its second suggestion:

var OutScopeSubSet = Enumerable.Except(FullSet, InScopeSubSet);

The Enumerable one runs ok but returns the whole first set without taking out any items.

If that's the case, you are probably getting reference comparisons on objects that are not identical. You might be able to do it by implementing a custom IEqualityComparer. The call becomes

var OutScopeSubSet = Enumerable.Except(FullSet, InScopeSubSet, new DynamicChildIdComparer());

And DynamicChildIdComparer is:

class DynamicChildIdComparer : IEqualityComparer<object>
{
    public bool Equals(object x, object y)
    {
        return ((dynamic)x).ChildID.Equals(((dynamic)y).ChildID);
    }

    public int GetHashCode(object obj)
    {
        return ((dynamic)obj).ChildID.GetHashCode();
    }
}

Upvotes: 1

Kunal
Kunal

Reputation: 1943

Are you looking for a "not in" SQL type operation

"Not in" in LINQ can be implemented like this :

var filterData = new List { "ListA", "ListB" };
var data= context.table.Select( c => c.id ).Except( filterData );

Upvotes: 0

Related Questions