How to use EXISTS in where condition of LINQ? - c#

I have gone through couple of similar questions but couldn't find what I wanted.
I need to find tags which has a ID in Answers table, since there could be multiple answers records containing the tag ID I need to take care of the duplicates. This is the reason why I cant perform simple join.
I thought about using an EXISTS but couldn't figure out the way to do it yet.
This is the working SQL
SELECT DISTINCT TagName
FROM Tags tag
JOIN Answers ans ON ans.StID = tag.Id
WHERE tag.SchId = 472
AND ans.isValid = 1
This is what I tried in LINQ with no success
(from tag in Tags
where tag.Id.Any(from ans in Answers
where ans.StID == tag.Id
&& tag.SchId == 472
&& ans.isValid == true
select ans.ID)
select tag.TagName
It would be helpful if someone can suggest a way to correctly implement this query in LINQ.

You'll generally want to accomplish this by using the Enumerable.Any() method to pass in a function that will check if any items in your collection meet a given criteria :
var x = Tags.Where(t => t.SchId == 472 && Answers.Any(a => a.StId == tag.Id && a.isValid))
.Select(t => t.TagName)
.Distinct();
This should give you a list of distinct tags that have a SchId of 472 and have at least one valid answer.

Look into the Distinct method which will get rid of your duplicates. Try the code below.
(from tag in Tags
where tag.Id.Any(from ans in Answers
where ans.StID == tag.Id
&& tag.SchId == 472
&& ans.isValid == true
select ans.ID).Distinct(ans => ans.ID)
select tag.TagName

Related

Linq nested loop search one specific top level element , collection within collections

I want to get the company whose employees id card issued with the specific number, sort of finding the exact element inside nested collection.
Using first or default 3 times does not seems to be a correct way.
> var company = cprIdentificationReply.Companies
> .FirstOrDefault(x => (x.Employee
> .FirstOrDefault(y => (y.IDCardIssued
> .FirstOrDefault(z => z.CardNumber
> .Equals(number,StringComparison.InvariantCultureIgnoreCase))) != null)
> != null));
What can be a proper way of achieving the same?
You may want to use the Any extension method:
var companies = cprIdentificationReply.Companies
.Where(x => (x.Employee
.Any(y => (y.IDCardIssued
.Any(z => z.CardNumber
.Equals(number, StringComparison.InvariantCultureIgnoreCase)
)
)
).ToList();
If you want better looking code why don't use LINQ query syntax.
I always find it easier to read LINQ query when looking at someone else's code, especially for complex operations.
Something like this:
var company = (from company in cprIdentificationReply.Companies
from empl in company.Employee
from idCardIss in empl .IDCardIssued
where idCardIss.CardNumber.Equals(number, StringComparison.InvariantCultureIgnoreCase)
select c).FirstOrDefault();

Linq2SQL choose IDs where join returns negative

I am attempting to query for an ID from table that needs to be joined with a negative result. In other words choose all the ScacIDs where that ScacID is not present in the joined table ScacSetup. This query returns no result.
var tasksNotAssociated = from scac in db.Scacs
where !db.ScacSetupTasks.Any(s => s.ScacTaskID == taskID)
group scac by scac.ScacCode into scacNotAssociated
select scacNotAssociated.FirstOrDefault();
Great and yes my solution was to use the left join that was provided by my navigation property; ScacSetupTasks. Guess I should have posted my navigation property and tagged with Entity Framework. OK, here is what I found to work and is essentially a left join where leftside == null as suggested by MarcinJeraszek, thanks buddy.
var scacsNotAssociated = db.Scacs.Where(s => s.ScacSetupTasks.Count(sst => sst.ScacTaskID == taskID) == 0);

WHERE clause in LINQ statement that pulls specific match or everything if no match found

I am trying to write a LINQ statement that will pull all the items from a table where the column Type matches what the user selects in a dropdown menu but if no matches are found then it returns ALL the items from the table regardless of the Type. I have gotten it to return all the items that match the user’s selection but I cannot figure out what code needs to be added so that if no matches are found it defaults to pulling all the items in the table.
Current Code:
(from i in db.ItemTypeTranslations
join st in db.SectionTranslations
on i.ItemType.SectionID equals st.SectionID
where i.CultureID == 1 && i.ItemType.SectionID == SelectedSection
select new
{
st.SectionID,
st.Title,
i.ItemTypeName
}).ToList();
You can use the ? operator to turn your where clause into a conditional and have your current select as the successful branch and the select that returns everything as the unsuccessful branch.
Similar question asked on MSDN
How about
where i.CultureID == 1 && (i.ItemType.SectionID == SelectedSection || String.IsNullOrEmpty(SelectedSection))
I am assuming that SelectedSection is a string. If not, the principle will be the same: Where (SectionID == SelectedSection OR SelectedSection == some-default-value)
Edit: I just re-read your question, and realized that I'm answering the wrong question.
Thanks Maggy May. That helped me a lot I ended up with this code that looks to be working:
(from i in db.ItemTypeTranslations
join st in db.SectionTranslations
on i.ItemType.SectionID equals st.SectionID
where (SelectedSection == 0 ? true : i.ItemType.SectionID == SelectedSection) && i.CultureID == 1
select new
{
i.ItemTypeID,
st.Title,
i.ItemTypeName
}).ToList();

has-relation in linq-statement?

I have three tables. Question, Discipline and QuestionHasDiscipline. QuestionHasDiscipline holds the relation between Question and Discipline. They all have an unique id-column to identify them.
I am trying to write a linq-statement that returns all the questions that have a certain discipline.
What I have begun doing is this:
var questions = (from q in context.Questions
where (from d in context.QuestionHasDiscipline
where d.QuestionId == q.QuestionId
) ...
But it obviously is horribly wrong. I've tried different approaches but now I turn to the greater minds.. Any suggestions?
You can use .Any() with a predicate.
from q in context.Questions
where context.QuestionHasDiscipline.Any(d => d.QuestionId == q.QuestionId)
select q;

Linq-to-SQL statement issue

I am basically looking to bind a search query to a gridview which is nice, but this must be done by a users input query (sort of like a search function). I can get single values and rows returned, but how would I get it to search all columns in my database for the inputted values and return it?
My code so far is:
Void SearchFunction()
{
TiamoDataContext context = new TiamoDataContext();
var search from p in context.UserProfiles
where p.DanceType == UserSearchString
select p;
UserSearchGrid.DataSource = search;
UserSearchGrid.DataBind();
}
I tried p.equals but am pretty sure thats not the way to go about it.
It looks like your query sytax is a little off. It should look like:
var search = from p in context.UserProfiles
where p.DanceType == UserSearchString
select p;
Since you're trying to query multiple columns, you're going to have to chain the names of the columns you're looking at with or's:
var search = from p in context.UserProfiles
where p.DanceType == UserSearchString ||
p.Name == UserSearchString ||
p.SomeOtherStringColumn == UserSearchString
select p;
Or if you want to use the Lambda syntax:
var search = context.UserProfiles.Where(p => p.DanceType == UserSearchString ||
p.Name == UserSearchString ||
p.SomeOtherStringColumn == UserSearchString);
Keep in mind that using either of these methods implies that p.DanceType is a string type.
If you want it to search every column in the table, then you have to tell it to search every column in the table.
var search =
from p in context.UserProfiles
where
p.DanceType == UserSearchString ||
p.Foo == UserSearchString ||
p.Bar == UserSearchString
select p;
That's all there is to it. There's no magic operator that will do it automatically (there can't be - some columns might not even be strings).
Keep in mind that this will likely be very slow, as the query optimizer won't be able to pick a single index that can handle this entire query.
As an aside, this "search" only tests for pure equality. You might want to use StartsWith or Contains for a prefix or substring search, respectively.

Categories