lhan
lhan

Reputation: 4635

LINQ query - exception thrown if no match?

Consider the following class:

Public Class Employee
   Public State As String   
   Public Dept As String
   Public Status as Integer
End Class

I need to query a distinct value from a listEmployees which is four records:

oEmp = New Employee
oEmp.Dept = "HR"
oEmp.State = "Kansas"
oEmp.Status = 1
listEmployees.Add(oEmp)

oEmp = New Employee
oEmp.Dept = "HR"
oEmp.State = "Texas"
oEmp.Status= 3
listEmployees.Add(oEmp)

oEmp = New Employee
oEmp.Dept = "HR"
oEmp.State = "Texas"
oEmp.Status= 5
listEmployees.Add(oEmp)

oEmp = New Employee
oEmp.Dept = "DEV"
oEmp.State = "Texas"
oEmp.Status= 7
listEmployees.Add(oEmp)

What I need the query to do is return distinct Deparments where State = 'Texas'. But I need be able to add multiple cases to the Where clause. So another query might need to return distinct Status's where State = 'Texas', and Dept = 'HR'.

There will always be only one field which I need distinct.

So the results to my first query example would be "HR" and "DEV" because those are the distinct Departments that have "Texas" as the State. The results to the second query would be "3" and "5" because those are the distinct Status's where the State is "Texas" and the Department is "HR".

UPDATE:

Here's what I've got working for Query #1:

Dim test = (From emp As Employee In listEmployees
            Where emp.State = "Texas"
            Select emp.Dept).Distinct()

However, if I specify something for State that doesn't exist, such as "TTexas", I get the following exception (the code doesn't blow up but if I inspect the test variable in Visual Studio after this line executes, I get this):

Exception of type 'System.Linq.SystemCore_EnumerableDebugViewEmptyException' was thrown. at System.Linq.SystemCore_EnumerableDebugView`1.get_Items()

Is this normal LINQ behavior?

Upvotes: 2

Views: 3755

Answers (3)

Gert Arnold
Gert Arnold

Reputation: 109185

After your edit (new issue). Yes this is "normal" (as in: intended) behaviour. See the code of get_Items:

public T[] Items
{
    get
    {
        List<T> tempList = new List<T>();
        IEnumerator<T> currentEnumerator = this.enumerable.GetEnumerator();

        if (currentEnumerator != null)
        {
            for(count = 0; currentEnumerator.MoveNext(); count++)
            {
                tempList.Add(currentEnumerator.Current);
            }
        }
        if (count == 0)
        {
            throw new SystemCore_EnumerableDebugViewEmptyException();
        }
        cachedCollection = new T[this.count];
        tempList.CopyTo(cachedCollection, 0);
        return cachedCollection;
    }
}

I wonder why a debug view should throw an exception and not just show "count = 0" or something, but that's probably just ignorance.

Upvotes: 2

Evgraf
Evgraf

Reputation: 187

Create your own comparer in order to detect items equality

public class Comparer : IEqualityComparer<Employee>
{
    public bool Equals(Employee x, Employee y)
    {
        throw new NotImplementedException();
    }

    public int GetHashCode(Employee obj)
    {
        throw new NotImplementedException();
    }
}

And use it

... .Distinct(new Comparer());

Upvotes: 0

Jason Sperske
Jason Sperske

Reputation: 30436

Distinct means across all elements of a row. If you have two rows where all returned elements are the same, distinct will reduce it to one row, but if even one element is different then both rows will be returned after distinct. You could override this (as seen here and in Evgraf's answer) of course. Grouping operators are more likely what you are looking for (here is an example in VB.net).

Upvotes: 0

Related Questions