I need to return true when any record either has an Indemnity type of bond, or has the bond waived. I think because of the way inner joins are happening this is not working.
var HasBondorWaived = (from a in context.Allocations
join p in context.Permits on a.PermitGUID equals p.GUID
join i in context.Indemnities on a.IndemnityGUID equals i.GUID
join t in context.IndemnityTypes on a.IndemnityAreaTypeGUID equals t.GUID
where (p.GUID.Equals(PermitGuid)
&& (t.Description.Equals("Performance Bonds") || t.Description.Equals("Payment Bonds")))
|| p.BondRequirementWaived where p.GUID.Equals(PermitGuid)
select a).Any();
return HasBondorWaived;
I'm getting closer. My validation is now working correctly in the case of "Performance Bond" or "Payment Bond", but is not working in the case of BondRequirementWaved. This is a bool in the EF, and a bit in SQL server. In the case of BondRequirementWaved, it is returning false.
using (var context = new KEPTEntities())
{
var HasBondorWaived = (from a in context.Allocations
join p in context.Permits on a.PermitGUID equals p.GUID
join i in context.Indemnities on a.IndemnityGUID equals i.GUID
join t in context.IndemnityTypes on i.IndemnityTypeGUID equals t.GUID
where (p.GUID.Equals(PermitGuid)
&& (t.Description.Equals("Performance Bonds")
|| t.Description.Equals("Payment Bonds")
|| p.BondRequirementWaived))
select a).Any();
return HasBondorWaived;
The second where clause won't work as you expect. You need to remove it.
You probably want this:
where (p.GUID.Equals(PermitGuid)
&& (t.Description.Equals("Performance Bonds") || t.Description.Equals("Payment Bonds")
|| p.BondRequirementWaived))
Assuming you have navigation properties set up, this is much cleaner:
var HasBondorWaived=context.Allocations
.Where(a=>a.Permits.GUID.Equals(PermitGuid))
.Any(a=>a.Permits.BondRequirementWaived ||
a.Indemnities.Any(i=>i.IdemnityType.Description=="Performance Bonds" || i.IdemnityType.Description=="Payment Bonds"));
Kind of hard to see what you actually asking for, but I think that is what you want based on your question and without a clear entity model.
Related
I have a linq query that is checking to see if a value exists, given criteria. It joins Permits, AccessControlTypes, and EntanceEnhancementHistories, all on their Guid FKs. It checks Permits of Type "Full" or "Limited" to see if they have any associated EntranceEnhancementHistories.
bool LimitedorFullEntranceEnhancementValue = (
from p in context.Permits
join a in context.AccessControlTypes on p.EntranceAccessControlTypeGUID equals a.GUID
join e in context.EntranceEnhancementHistories on p.GUID equals e.PermitGUID
where p.GUID.Equals(PermitGuid)
&& ((a.Description.Equals("Full") || a.Description.Equals("Limited"))
&& (e.GUID == null))
select e).Any();
return LimitedorFullEntranceEnhancementValue;
This query is failing. It's returning false in the case that is does find description of full or limited, but does not find an entrancehancementvalue (it should be null).
It works properly without the check for a null entranceenhancementvalue, and I'm able to get it working with 2 queries, but I don't think this should be necessary.
You're using an "inner join" on p.GUID equals e.PermitGUID, which means you'll only see results where an e.PermitGUID exists. I think you want something more like this:
(from p in context.Permits
join a in context.AccessControlTypes on p.EntranceAccessControlTypeGUID equals a.GUID
where p.GUID.Equals(PermitGuid)
&& ((a.Description.Equals("Full") || a.Description.Equals("Limited"))
&& !context.EntranceEnhancementHistories.Any(e => p.GUID == e.PermitGUID)
select p).Any();
You need to use a LEFT OUTER JOIN if you expect to see rows where the Guid key is null:
(from p in context.Permits
join a in context.AccessControlTypes on p.EntranceAccessControlTypeGUID equals a.GUID
join t in context.EntranceEnhancementHistories on p.GUID equals e.PermitGUID into leftJoin
join e in leftJoin on p.DefaultIfEmpty()
where p.GUID.Equals(PermitGuid)
&& ((a.Description.Equals("Full") || a.Description.Equals("Limited"))
&& (e.GUID == null))
select e).Any();
return LimitedorFullEntranceEnhancementValue;
This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 8 years ago.
I have the linq below. Since I am querying from 2 datacontexts, I've brokendown the tables into var list. But then, I have the error "Object reference not set to an instance of an object". This happens because edr is null.
var meetingsQuery = (from s in this.ModelContext.Meetings select s).ToList();
var deliverablesQuery = (from s in this.ModelContext.Deliverables select s).ToList();
var deliverableDatesQuery = (from s in this.ModelContext.DeliverableDates select s).ToList();
var refDateTypesQuery = (from s in this.ModelContext.RefDateTypes select s).ToList();
var refDeliverablesQuery = (from s in this.ModelContext.RefDeliverables select s).ToList();
var updatesQuery = (from s in this.ArenaUpdateBASEModelContext.Updates select s).ToList();
var updateQCsQuery = (from s in this.ArenaUpdateBASEModelContext.UpdateQCs select s).ToList();
var submissionUpdates = (from e in meetingsQuery
from edr in deliverablesQuery.Where(dr => dr.MeetingId == e.MeetingId && !dr.DeletedFlag).DefaultIfEmpty()
from ed in deliverableDatesQuery.Where(d => d.DeliverableId == edr.DeliverableId && !d.DeletedFlag && d.RefDateTypeId == 1).DefaultIfEmpty()
from ed2 in deliverableDatesQuery.Where(d2 => d2.DeliverableId == edr.DeliverableId && !d2.DeletedFlag && d2.RefDateTypeId == 2).DefaultIfEmpty()
join ret in refDateTypesQuery on ed.RefDateTypeId equals ret.RefDateTypeId
join rdt in refDeliverablesQuery on edr.RefDeliverableId equals rdt.RefDeliverableId
join upd in updatesQuery on edr.RefDsgnSubmissionTypeId equals upd.UpdateId
join uqc in updateQCsQuery on upd.UpdateId equals uqc.UpdateId
where
!e.DeletedFlag && !ret.DeletedFlag && !rdt.DeletedFlag && !upd.DeletedFlag && !uqc.DeletedFlag && e.ProjectId == arenaPiD// && rdt. .ObjectIdLink == "Update_UpdateId"
&& uqc.RefQCId == 6 // Distributed
&& uqc.RefQCStatusId == 2 // Complete
orderby e.ScheduledDT descending
select new
{
e.MeetingId,
e.ScheduledDT,
edr.DeliverableId,
edr.RefDeliverableId,
rdt.DeliverableAbbrv,
UpdateId = edr.RefDsgnSubmissionTypeId != null ? edr.RefDsgnSubmissionTypeId : 0,
RefRecommendationId = upd.RefRecommendationId != null ? upd.RefRecommendationId : 0,
uqc.RefQCId,
uqc.RefQCStatusId,
DeadlineDate = ed != null ? ed.DeliverableDateValue.ToString() : "",
ActualDate = ed2 != null ? ed2.DeliverableDateValue.ToString() : ""
}).ToList();
There's a big difference to how DefaultIfEmpty works for Linq To Objects vs Linq To SQL, which is tied into the difference between how nulls are handled between the two.
In SQL an empty record from a LEFT OUTER JOIN is populated with null values. Since your SQL never refer to the record itself this is not a problem. When you write edr.DeliverableId for an unmatched edr, the result is null.
Linq to SQL is different. When you try to reference any field or property of an unmatched edr the resultant error is exactly what you have seen. Every reference to edr after the DefaultIfEmpty call needs to be checked first to see if edr is valid.
Beyond the immediate error however...
You've mixed a couple of join forms - inner and outer - in that query, and the result is convoluted and unexpected. The problems you're taking on with DefaulIfEmpty for an outer join are negated with a subsequent inner join that depends on the outers. Which means that you are going through all the pain and suffering without any of the pay-off.
This block of joins:
join ret in refDateTypesQuery on ed.RefDateTypeId equals ret.RefDateTypeId
join rdt in refDeliverablesQuery on edr.RefDeliverableId equals rdt.RefDeliverableId
join upd in updatesQuery on edr.RefDsgnSubmissionTypeId equals upd.UpdateId
join uqc in updateQCsQuery on upd.UpdateId equals uqc.UpdateId
Every one of those depends ultimately on the outer join for edr, resulting in an output that - even if you put the time in to get the outer join side effects figured out - will negate the effects of DefaultIfEmpty.
You need to re-think your logic.
I suggest breaking this thing down into a series of intermediate queries. Build the query up one step at a time, joining the results in the final stage.
For instance, you have ed as an outer join which is then subjected to an inner join with rdt and further filtered by the properties of rdt in your where clause. Scrape all that out and put it in an intermediate, then join against it later. Do the same with edt: create an intermediate that join the parts. Flatten out the results for use in the final query.
Incidentally, you don't necessarily need to bring all of that data into memory. Even if your data is on different physical servers you can often still get Linq to SQL to talk to them. When you're targeting SQL Server for example you can specify a 3- or 4-part name for the Table attribute to access data in other databases on the same server or databases on linked servers. Might be useful.
I have a form that allows the user to perform a myriad of searches. The table(s) that need to be joined differ depending on the search criteria entered. (My example below is very simplistic because both tables use the same sub-tables to join on, but the actual problem is not as simple.)
I've been using a technique I call LINQ stacking, like this:
IQueryable<LogENT> results = Context.AssignedLogsENT.Where(l => l.AgencyId);
if(txtFirstName.Text != null)
results = from r in results
join a in Context.LogAssignmentsENT on r.DisplayLogId equals a.LogId
join p in Context.PersonsENT on a.ObjectId equals p.DisplayPersonId
&& !a.Deleted &&
p.FirstName.StartsWith(Object.FirstName)
select r;
if(txtLastName.Text != null)
results = from r in results
join a in Context.LogAssignmentsENT on r.DisplayLogId equals a.LogId
join p in Context.PersonsENT on a.ObjectId equals p.DisplayPersonId
&& !a.Deleted &&
p.LastName.StartsWith(Object.LastName)
select r;
So you see if a certain text field is set, I add to the query as necessary. This actually works fine, except that when I use SQL Profiler to view the generated query, it is INNER JOINing the tables each time I add a new criterion.
i.e. the LogAssignments table is included 3, 4, 5 times. Is there a way I can prevent it from JOINing the same table more than once?
Or, is there a better way I can do this? I've looked at Predicate Builder however it doesn't seem to permit joining tables, which is a requirement in my case.
Thanks!
IQueryable<LogENT> results = Context.AssignedLogsENT.Where(l => l.AgencyId);
results = from r in results
join a in Context.LogAssignmentsENT on r.DisplayLogId equals a.LogId
join p in Context.PersonsENT on a.ObjectId equals p.DisplayPersonId
&& !a.Deleted
select r;
if(txtFirstName.Text != null)
results = from r in results
p.FirstName.StartsWith(Object.LastName)
select r;
if(txtLastName.Text != null)
results = from r in results
p.LastName.StartsWith(Object.LastName)
select r;
If you use just one query, you could modify it something like this:
results = from r in results
join a in Context.LogAssignmentsENT on r.DisplayLogId equals a.LogId
join p in Context.PersonsENT on a.ObjectId equals p.DisplayPersonId
&& !a.Deleted &&
(txtFirstName.Text != null || p.FirstName.StartsWith(Object.FirstName)) &&
(txtLastName.Text != null || p.LastName.StartsWith(Object.LastName))
select r;
You can build your base result and then dynamically add the where clauses.
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.
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.