tags:

views:

465

answers:

2

Hi,

I'd like to get with LINQ an employee list, these employees must have in the TypeOfWorks list the typeofWork passed (Id) in argument

  public class Employee 
    {   
        public virtual IList<EmployeeTypeOfWork> TypeOfWorks { get; set; }
    }

    public class EmployeeTypeOfWork 
    {
        public virtual Guid Id { get; set; }
        public virtual Employee Employee { get; set; }
        public virtual TypeOfWork TypeOfWork { get; set; }
    }

    public class TypeOfWork 
    {
        public virtual Guid Id { get; set; }
    }


    public IList<Employee> ListWithTypeOfWork(IList<Employee> Employees, 
Guid typeOfWorkId)
    {     
        ?????       
    }

I tried this but I missed something I think

        var res = from p in Employees
        where (from pp in p.TypeOfWorks 
    where pp.TypeOfWork.Id == guid select pp.Id).Contains(p.Id)
        select p;

Thanks,

+3  A: 

Try the following

var res = Employees
  .Where(x => x.TypeOfWorks.Any(w => w.Id == guid))
JaredPar
Why not replace the `Where` with `Any` so you can shorten it? :)
Ryan Versaw
@Ryan, good call. I forget there is an overload of Any which accepts a predicate .
JaredPar
if one of those TypeOfWorks is a null that code will throw and exception.
blesh
@blesh, true but the best way to represent a lack of values in a collection is with an empty collection. Having a null collection just complicates code which uses the colleciton
JaredPar
No, I mean if it's an IList<T> then it could be a list containing: {T, T, T, null, T, T, T, null} provided T is a class, which in this case it is. So while it's iterating through the source enumeration, it would throw and exception when it calls the predicate w.Id == guid, because it will be trying to get a "Id" property from a null reference.
blesh
@blesh, What value is there in putting a null into a collection of any type? Having such a value adds 0 useful information and instead adds unusable information. That would be a bug in the code, not my answer.
JaredPar
@JaredPar, You'll have talk to Microsoft about that, they're the ones who made you able to add a null to an IList. The value of it is debateable, I suppose, but not with me, as I didn't create that functionality.Regardless, your code can and will break in that scenario.
blesh
@blesh, Just because it's legal doesn't mean it should ever be used in code. It's perfectly reasonable to set reasonable invariants for your projects. Users can technically make IEnumerable<T>.GetEnumerator throw a StackOverflowException if they wish, but I noticed you didn't check for that case.
JaredPar
I have to agree with Jared. I would keep my code as Jared has it, as this is the intended functionality. If another portion of code inserts a null value, that code must have a bug in it, which this piece will expose. I would very much prefer that this is exposed as opposed to covering it up.
Ryan Versaw
Also, downvoting this answer because of these explanations is absurd.
Ryan Versaw
+1  A: 
public IEnumerable<Employee> ListWithTypeOfWork(IList<Employee> Employees, Guid typeOfWorkId)
{     
    return from emp in Employees
        where emp.TypeOfWorks.Any(x => x != null && x.Id == typeOfWorkId)
        select emp;          
}
blesh
Kris-I
Just for info, when I ask Linq code why everybody answer with lambda expression, is there specific reason ?
Kris-I
@Kris-l: FirstOrDefault(Func<>) and Any(Func<>) are pretty much the exact same method call, you can check in Reflector. The only difference is that FirstOrDefault(Func<>) returns an object, and Any(Func<>) simply returns a bool. When you're just testing a list of reference types, returning the bool is slightly more efficient. If you're testing a list of value types, then it doesn't necessarily matter I suppose, but it's probably still a little more efficient to return a bool.
blesh