Im struggling with some linq
I want everything from the CustomerDiscountGroups table, then join a column from another table. If the where condition shows ther are no CustomerDiscounts i still want it to show all the colums from CustomerDiscountGroups table, and state 0 for Discount_PC ( a decimal)
heres my attempt
from c in CustomerDiscountGroups
join d in CustomerDiscounts on c.ID equals d.Discount_ID into cd
from cdi in (from f in cd
where f.AccountNo == "test"
select f).DefaultIfEmpty()
select new
{
c.ID,
c.DisplayName,
c.Image,
c.Added,
c.Added_by,
c.Edited,
c.Edited_by,
//cdi.Discount_PC
}
DefaultIfEmpty will make cdi null, even though it is of the type CustomerDiscounts. You have to handle that situation in your select clause:
select new
{
c.ID,
c.DisplayName,
c.Image,
c.Added,
c.Added_by,
c.Edited,
c.Edited_by,
Discount_PC = cdi == null ? 0 : cdi.Discount_PC
}
It is a bit awkward to have to write out a ternary operator for it and in fact, in C#6 there will probably be a new short hand operator for this.
Related
I have a query that has a where condition to check and find addresses that were added after a certain date. The date field is not required so I want Date field in where condition to be only considered if it is not 1/1/0001.
dtmDate is the parameter that is being passed
Query
from b in _context.customer
join d in _context.Address on b.id equals d.Id
join e in _context.units on d.Id equals e.Id
where (req.dtmDate.Year != 1 && d.DateAdded >= req.dtmDate)
select new modelAddress
{
address= d.address
}
But this is not working. It is not returning any rows
I'd leverage the fact that LINQ queries are not executed when you write them, so you can add clauses conditionally after you've created a base query:
var query = from b in _context.customer
join d in _context.Address on b.id equals d.Id
join e in _context.units on d.Id equals e.Id;
if(req.dtmDate.Year != 1)
query = query.Where(d.DateAdded >= req.dtmDate);
var result = query.Select(
new modelAddress
{
address= d.address
}
);
I prefer this because I've previously run into issues, particularly with EF LINQ queries when the Where clause contains something that evaluates to true locally with in the code, rather than as something the DB will evaluate. It seems to work out better when "wildcarding" DB queries, to use a pattern of "if x is true then add-another-where-clause" rather than saying "where(local-value-of-x-equals-local-constant OR some-db-data-value-equals-y)"
If I understand you correctly, you have a DateTime object called req.dtmDate that may be set to a default value, and you want to return all items where the item's DateAdded field is greater than req.dtmDate, unless req.dtmDate is 1/1/0001, in which case all records should be returned.
If that's the case, I think you could just modify your existing code to:
where (req.dtmDate.Year == 1 || d.DateAdded >= req.dtmDate)
I am trying to do a left join with a where clause in linq.
I have leadsQuery table with 2500 rows. I want to join the LeadCons table into it. For a lead there can be multiple entries in the LeadCons table, hence I want to join only when the Status match. Else I want the fields to be NULL.
var data = from lead in leadsQuery
join lcs in context.LeadCons on lead.ID equals lcs.LeadId into leadsWithCons
from lcs in leadsWithCons.DefaultIfEmpty()
where lead.Status == lcs.Status
select new
{
LeadId = lead.ID,
Source = lead.Source.ToString(),
};
This query gives me ~1500 rows and leadsQuery has 2500. What am I doing wrong here?
A late answer, hoping it is still helpful:
First, you aren't selecting any values from LeadCons, so what is the purpose of a join?
I shall assume maybe you want to extend your select, so let us say you want to select the property foo, so my next question: Why do you need a left join in your case? You can simply do a select:
var data = from lead in leadsQuery
select new
{
Foo = context.LeadCons.Where(lcs => lead.Status == lcs.Status).SingleOrDefault().foo
LeadId = lead.ID,
Source = lead.Source.ToString(),
};
This way you have the same number of items and for each item the desired foo value.
Have you tried just changing the your join to a join with multiple conditions, and then removing the where 'status equal status'
from lead in leadsQuery
join lcs in context.LeadCons on new {
p1 = lead.ID,
p2 = lead.Status
}
equals
new {
p1 = lcs.LeadId,
p2 = lcs.Status
}
you can have a look at this nice article:
https://smehrozalam.wordpress.com/2010/04/13/linq-how-to-write-queries-with-complex-join-conditions/
I have a question with Linq to Sql query in C#.
I have this query:
from A in context.General
join B in context.Applications on A.ID equals B.ID
from G in context.Notes
//where (G.CODE == A.NoteID || G.CODE == A.NoteID2 || G.CODE == A.NoteID3)
join X in context.Att on B.AttID equals X.AttID
select new
{
A.SomeStuff,
B.SomeStuff
G.NOTE_TEXT
});
My question is, which NOTE_TEXT the query will return, for example if in some case one record has three codes that match with the G.CODE field it will return three NOTE_TEXT or only the first one? Or in another case what happens if one record has only one match with the G.CODE field, and the others two has an empty value, only return that match or nothing?
Thank you so much, and please let me know if I'm not clear in my question.
Is there any way to set if in a linq statement?
return(from x in db.products where x.id == id
if(x.type == 1){
join y in db.category1 on x.idItem equals y.id
}else if(x.type == 2){
join z in db.category2 on x.idItem equals z.id
}
select New {....}).ToList();
I know this code is wrong but my question is:
What's the best way to implement this?
Note, that the following does not solve the problem that the OP is having because the join predicate depends on each item. The following helps if the condition is known for the entire query at once:
You split the query:
var part1 = from x in db.products where x.id == id select x;
var part2 =
b ? (from x in part1 join db.category1 select { x, joinedItem }) :
(from x in part1 join db.category2 select { x, joinedItem });
Quickly written up. You need to make the anonymous types on both queries compatible. That's the only important thing.
You could do a LEFT JOIN and one of the conditions of the LEFT JOIN could be the condition you have in the IF clause. So, you always do all the LEFT JOINs but they will only return results when the condition you have in the IF cluase is true.
Another way, with much better performance, is to create a Stored Procedure and call it from EF.
I want to do a JOIN with LINQ using an OR statement.
Here is the SQL query I'm starting with:
SELECT t.id
FROM Teams t
INNER JOIN Games g
ON (g.homeTeamId = t.id OR g.awayTeamId = t.id)
AND g.winningTeamId != 0
AND g.year = #year
GROUP BY t.id
I'm having trouble converting that ON clause to LINQ. This is where I'm at:
var y = from t in db.Teams
join g in db.Games on t.ID equals g.AwayTeamID //missing HomeTeamID join
where g.WinningTeamID != 0
&& g.Year == year
group t by t.ID into grouping
select grouping;
I think I could use:
join g in db.Games on 1 equals 1
where (t.ID == g.HomeTeamID || t.ID == g.AwayTeamID)
and this works but seems kind of seems hacky. Is there a better way?
I struggled with this as well until I found the following solution, which worked well for my situation:
var y = from t in db.Teams
from g in db.Games
where
(
t.ID == g.AwayTeamID
|| t.ID == g.HomeTeamID
)
&& g.WinningTeamID != 0
&& g.Year == year
group t by t.ID into grouping
select grouping;
Under the covers, your solution probably works very close to this one. However, I bet this one is just a bit faster if you benchmark it since it is not JOINING every item in the first dataset with every item in the second dataset, which could be a disaster if either (or both) dataset were really big.
The where clause applies a boolean condition, so using "||" is the way to go. You can chain multiple where clauses but I believe that will give you a "and" operation, rather than an "or".
I think you can do like this:
from t1 in db.Table1
// inner join with OR condition
from t2 in db.Table2 where t1.col1 == t2.col1 || t1.col2 == t2.col2
// normal inner join
join t3 in db.Table3 on t1.col1 equals t3.col1
// inner join with complex condition
join t4 in db.Table4 on t2.col4 equals t4.col4 where t2.col5.Contains(t4.col5)
// left join with OR condition
from t5 in db.Table5.Where(x => x.col5 == t1.col5 || x.col6 == t1.col6).DefaultIfEmpty()
select new {
x = 1 // select whatever you want here
}
The underlying SQL query probably won't use native sql joins but the above is just a way to make your code look pretty and organized.