Dynamic variable in LINQ - c#

I have the following statement in LINQ:
var eventsWithTag = (from occurence in occurrences1
join eventTag in serviceContext.CreateQuery("adx_eventtag_event")
on occurence.Event.GetAttributeValue<Guid>("adx_eventid") equals eventTag.GetAttributeValue<Guid>("adx_eventid")
join tag in serviceContext.CreateQuery("adx_eventtag")
on eventTag.GetAttributeValue<Guid>("adx_eventtagid") equals tag.GetAttributeValue<Guid>("adx_eventtagid")
where tag.GetAttributeValue<string>("adx_name") == "scotland"
select occurence).OrderBy(x => x.Start);
This works fine with the fixed string search of "Scotland" in this instance. However I need to replace that to reflect the current page topic. So essentially I need to replace
== "scotland"
with
== getBranch()
where getBranch returns the relevant branch name as a string.
This would lead me to try
eventsWithTag = (from occurence in occurrences1
join eventTag in serviceContext.CreateQuery("adx_eventtag_event") on occurence.Event.GetAttributeValue<Guid>("adx_eventid") equals eventTag.GetAttributeValue<Guid>("adx_eventid")
join tag in serviceContext.CreateQuery("adx_eventtag") on eventTag.GetAttributeValue<Guid>("adx_eventtagid") equals tag.GetAttributeValue<Guid>("adx_eventtagid")
where tag.GetAttributeValue<string>("adx_name") == getBranch()
select occurence).OrderBy(x => x.Start);
But this doesnt work, and from what little I know of LINQ it is because you cant use variables in this way.
So my question is: How can I use the LINQ query above with a dynamic value for the branch.
Please note: I have seen other posts about this but I evidently don't have the LINQ knowledge to transfer them to my specific needs. Just yet!

Everything looks right so I'd double check your getBranch()...
if this works:
var branch = "scotland";
eventsWithTag =
(from occurence in occurrences1
join eventTag in serviceContext.CreateQuery("adx_eventtag_event") on occurence.Event.GetAttributeValue<Guid>("adx_eventid") equals eventTag.GetAttributeValue<Guid>("adx_eventid")
join tag in serviceContext.CreateQuery("adx_eventtag") on eventTag.GetAttributeValue<Guid>("adx_eventtagid") equals tag.GetAttributeValue<Guid>("adx_eventtagid")
where tag.GetAttributeValue<string>("adx_name") == branch
select occurence)
.OrderBy(x => x.Start);
Then p.s.w.g's answer should work, and your issue lies with getBranch returning a value that doesn't match any records...
On a slightly different matter, I'm slightly confused as to why you need to get the actual attributes in your equals statement, because according to this, it should work fine like this:
var branch = "scotland";
eventsWithTag =
(from occurence in occurrences1
join eventTag in serviceContext.CreateQuery("adx_eventtag_event") on occurence.Event["adx_eventid"] equals eventTag["adx_eventid"]
join tag in serviceContext.CreateQuery("adx_eventtag") on eventTag["adx_eventtagid"] equals tag["adx_eventtagid"]
where tag["adx_name"] == branch
select occurence)
.OrderBy(x => x.Start);

You can just make the call beforehand:
var branch = getBranch();
eventsWithTag =
(from occurence in occurrences1
join eventTag in serviceContext.CreateQuery("adx_eventtag_event") on occurence.Event.GetAttributeValue<Guid>("adx_eventid") equals eventTag.GetAttributeValue<Guid>("adx_eventid")
join tag in serviceContext.CreateQuery("adx_eventtag") on eventTag.GetAttributeValue<Guid>("adx_eventtagid") equals tag.GetAttributeValue<Guid>("adx_eventtagid")
where tag.GetAttributeValue<string>("adx_name") == branch
select occurence)
.OrderBy(x => x.Start);

Related

how to access table from embedded where LINQ c#

Please note below is entirely made up for example sake. I have a similar query based on an sql code but couldn't translate it to LINQ to get correct value.
The sql basically looks like this:
select * from customers c
join proucts p on c.id = p.customerid
join credit r on r.customerid=c.id and ISNULL(r.trandate, c.registeredDate) >= c.registeredDate
I also tried to tweak the above sql and put the condition inside where and it also returns the same value I am getting in my #2 LINQ below(which is incorrect).
How can I use c (customer) inside .Where of credit? see code
1.
from c in customers
join p in products on c.id = p.customerid
join cr in credit.Where(r=> r.tranDate => c.registeredDate!=null?c.registeredDate : r.purchaseDate) on c.id=cr.customerid
...
2.
I know you would suggest why not just put it in a where below like below but I am getting incorrect value.
from c in customers
join p in products on c.id = p.customerid
join cr in credit on c.id=cr.customerid
where r.tranDate => c.registeredDate!=null?c.registeredDate : r.purchaseDate
Is there a workaround? I have tried tons of others but won't get me the correct one.
LINQ supports only equijoins. Any additional criteria should go to where clause. And yes, the other range variables are inaccessible from the join inner sequence, so the filtering should happen before or after the join.
So this SQL query:
select * from customers c
join products p on c.id = p.customerid
join credit r on r.customerid = c.id
and ISNULL(r.trandate, c.registeredDate) >= c.registeredDate
directly translates to this LINQ query:
from c in customers
join p in products on c.id equals p.customerid
join cr in credit on c.id equals cr.customerid
where (cr.tranDate ?? c.registeredDate) >= c.registeredDate
select new { c, p, cr };
Optionally, the condition
(cr.tranDate ?? c.registeredDate) >= c.registeredDate
can be replaced with
(cr.tranDate == null || cr.tranDate >= c.registeredDate)

Linq to Entities Joins

I have a question about joins when using Linq to Entities. According to the documentation the use on the join without a qualifier performs like a left outer join. However when I execute the code below, I get a count returned of zero. But if I comment out the three join lines I get a count of 1. That would indicate that the join are acting as inner join. I have two questions. One which is right inner or outer as the default? Second how do I do the other one i.e. inner or outer? The key words on inner and outer do not work.
var nprs = (from n in db.FMCSA_NPR
join u in db.FMCSA_USER on n.CREATED_BY equals u.ID
join t in db.LKUP_NPR_TYPE on n.NPR_TYPE_ID equals t.ID
join s in db.LKUP_AUDIT_STATUS on n.NPR_STATUS_ID equals s.ID
where n.ROLE_ID == pRoleId
&& n.OWNER_ID == pOwnerId
&& n.NPR_STATUS_ID == pNPRStatusId
&& n.ACTIVE == pActive
select n).ToList();
if (nprs.Count() == 0)
return null;
joins without keys operate like inner joins. I can't find it in the documentation at the moment, but I'll post an edit when I do. However, to perform a left outer join, here is a sample from 101 LINQ Samples: http://msdn.microsoft.com/en-us/vcsharp/ee908647#leftouterjoin
Joins in LINQ are inner by default. To do an outer join, you have to either do a manual "if-null-then" or write your own custom join operation.
Left-outer example with manual if-null:
var query = from person in people
join pet in pets on person equals pet.Owner into gj //inner
from subpet in gj.DefaultIfEmpty()
select new { person.FirstName, PetName = (subpet == null ? String.Empty : subpet.Name) }; //left outer
How to: Perform Left Outer Joins
How to: Perform Custom Join Operations

using "greater than or equal" operator in linq join operation [duplicate]

I had tried to join two table conditionally but it is giving me syntax error. I tried to find solution in the net but i cannot find how to do conditional join with condition. The only other alternative is to get the value first from one table and make a query again.
I just want to confirm if there is any other way to do conditional join with linq.
Here is my code, I am trying to find all position that is equal or lower than me. Basically I want to get my peers and subordinates.
from e in entity.M_Employee
join p in entity.M_Position on e.PostionId >= p.PositionId
select p;
You can't do that with a LINQ joins - LINQ only supports equijoins. However, you can do this:
var query = from e in entity.M_Employee
from p in entity.M_Position
where e.PostionId >= p.PositionId
select p;
Or a slightly alternative but equivalent approach:
var query = entity.M_Employee
.SelectMany(e => entity.M_Position
.Where(p => e.PostionId >= p.PositionId));
Following:
from e in entity.M_Employee
from p in entity.M_Position.Where(p => e.PostionId >= p.PositionId)
select p;
will produce exactly the same SQL you are after (INNER JOIN Position P ON E..PostionId >= P.PositionId).
var currentDetails = from c in customers
group c by new { c.Name, c.Authed } into g
where g.Key.Authed == "True"
select g.OrderByDescending(t => t.EffectiveDate).First();
var currentAndUnauthorised = (from c in customers
join cd in currentDetails
on c.Name equals cd.Name
where c.EffectiveDate >= cd.EffectiveDate
select c).OrderBy(o => o.CoverId).ThenBy(o => o.EffectiveDate);
If you have a table of historic detail changes including authorisation status and effective date. The first query finds each customers current details and the second query adds all subsequent unauthorised detail changes in the table.
Hope this is helpful as it took me some time and help to get too.

LINQ to SQL query not ordering properly, please help

var temp = (from assetVisit in db.AssetVisits
join assetBundle in db.AssetBundles on assetVisit.AssetID equals assetBundle.AssetID
join groupBundle in db.GroupBundles on assetBundle.BundleID equals groupBundle.BundleID
join userGroup in db.UserGroups on groupBundle.GroupID equals userGroup.GroupID
where assetVisit.CompanyID == companyID &&
userGroup.UserID == userID
select new { AssetID = assetVisit.AssetID, Count = assetVisit.AccessCounter }).Distinct();
IQueryable<Asset> final = (from t in temp
join asset in db.Assets on t.AssetID equals asset.AssetID
where asset.IsActive == true
&& asset.AssetTypeID == assetType
&& asset.ShowInResults == true
&& (asset.CompanyID == companyID || asset.CompanyID == -12081974)
orderby t.Count descending
select asset).Except(from companyAssets in db.Assets
join copiedAssets in db.Assets on companyAssets.AssetID equals copiedAssets.OriginalAssetID
where copiedAssets.CompanyID == companyID && companyAssets.CompanyID == -12081974 && copiedAssets.IsActive == true
select companyAssets);
return final.Take(limit);
OK so it's suppose to give back the assets in order based on t.Count but I think it might not be working because the .Count is actually not part of asset which is what is being selected, but I have no idea how to fix this.
As you can see there is an assetVisits table and an assets table, and I need to get back the assets in order of the assetVisits.AccessCount but I can't get it to work, what the hell??
You asked an almost identical question a couple of hours ago, and the answer is the same: do the ordering after you have selected the rows you want to order.
Change:
return final.Take(limit);
to:
var finalOrdered = from asset in final
join assetVisit in db.AssetVisits on asset.AssetID equals assetVisit.AssetID
orderby assetVisit.AccessCounter
select asset;
return finalOrdered.Take(limit);
You can also remove the premature 'orderby' from your own code, since it is not doing anything.
You query is missing the ordeby clause. You have one in a subquery, but placing orderby anywhere but on the outermost query expression is irelevant (except for when top is also used).
You have to specify the orderby on the outermost query.

LINQ join with OR

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.

Categories

Resources