4

Say I have two lists:

List<CanidateSkill> canidateSkills;
List<JobDesiredSkill> desiredSkills;

class CanidateSkill
{
    public Guid CanidateId { get; set; }
    public Guid SkillId { get; set; }
}

class JobDesiredSkill
{
    public Guid JobId { get; set; }
    public Guid SkillId { get; set; }
}

How do you determine if:

  1. At least one item in JobDesiredSkills is contained in CandidateSkills (matched on SkillId)

  2. All items in JobDesiredSkills are contained in CandidateSkills

I tried this, but get this error: Unable to create a constant value of type Only primitive types ('such as Int32, String, and Guid') are supported in this context.

 return from candidate in _db.Candidates                           
 where (candidate.CandidateSkills.Any(c => job.JobDesiredSkills.Any(j => j.SkillId == c.SkillId))) 
 select candidate;

I also tried this, but Contains expects a JobDesiredSkill object, but c is a CandidateSkillObject.

 return from candidate in _db.Candidates                           
 where CandidateSkills.Any(c => JobDesiredSkills.Contains(c)) 
 select candidate;

Thanks

2 Answers 2

7

There are two linq methods that fit your exact needs:

  1. IEnumerable.Any()
  2. IEnumerable.All()

Edit:

You need to select a "Projection" of the "Ids" in the collection to get an enumerable collection of them, then you can use any / all on those (you can't compare complex types without an explicit comparison object).

Here is a trivial example, I hope it helps.

List<Guid> skills = 
    new List<Guid>( Enumerable.Range( 0, 20 ).Select( n => Guid.NewGuid() ) );

List<CanidateSkill> canidateSkills = new List<CanidateSkill>
(
    Enumerable.Range( 0, 10 ).Select( c => new CanidateSkill() { CanidateId = Guid.NewGuid(), SkillId = skills.ElementAt( c ) } )
);

List<JobDesiredSkill> desiredSkills = new List<JobDesiredSkill>
(
    Enumerable.Range( 5, 15 ).Select( d => new JobDesiredSkill() { JobId = Guid.NewGuid(), SkillId = skills.ElementAt( d ) } )
);

var anyDesiredSkills = canidateSkills.Any( c => desiredSkills.Select( ds => ds.SkillId ).Contains( c.SkillId ) ); // true
var allDesiredSkills = canidateSkills.All( c => desiredSkills.Select( ds => ds.SkillId ).Contains( c.SkillId ) ); // false

(Note: I also edited your question to update the sample classes used in this code, hope you don't mind.)

Sign up to request clarification or add additional context in comments.

15 Comments

You can't use All to test if all items from one sequence are in another - you can only use All to test is all items in a sequence match a given predicate. I could be wrong though - example usage of 2) in this scenario?
@RPM you just have to construct the right predicate - eg JobDesiredSkills.All(j => CandidateSkills.Contains(j))
@RPM a.All( n => b.Contains( n ) ); ?
Lol, i've been owned, forgot about contains. Nice. :)
@RPM hah, we've all been there my friend.
|
0

I don't have Visual Studio at handy right now but it should be something like:

1.

 JobDesiredSkills.Where(j=>CandidateSkills.Any(c=>c.SkillId == j.SkillId)==true).ToList().Count()>0
2.
 JobDesiredSkills.Where(j=>CandidateSkills.Where(c=>c.SkillId == j.SkillId).ToList().Count()>0).ToList().Count()==JobDesiredSkills.Count()

1 Comment

This is actually what I tried originally, but I get this error: Unable to create a constant value of type 'JobDesiredSkill'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.