I want to learn why these two queries return different results.
This query returns 6:
var a = (from belg in contextArchive.Belgeler
join zrf in contextArchive.Zarflar on belg.Parent_ID equals zrf.ID
where belg.RefETTN == this.BelgeETTN
select new { zrf }).Count();
While this query returns 3:
var b = (from belg in contextArchive.Belgeler
join zrf in contextArchive.Zarflar on belg.Parent_ID equals zrf.ID
where belg.RefETTN == this.BelgeETTN
select new { zrf }).ToList();
countKabulRed = b.Count();
I believe there are some null values in b. The different between a and b is that a uses SQL's COUNT that neglects null values, while b's Count() includes both null and non-null values.
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)
Here is the problematic line:
var originalSummaryCandidates =
(from a in masterDB.tbl_thirty_second_summaries_multi_variant_associations
join d in masterDB.tbl_thirty_second_summaries_multi_variants on a.ThirtySecSummaryId equals d.ThirtySecondSummaryId_this
where d.DrugId == drugId &&
variantGenotypeIds.Contains(new int[] {a.VariantId, a.GenotypeId})
select d.ThirtySecondSummaryId_this)
.Distinct()
.ToList();
variantGeotpeIds is of type List<int[]>. Both a.VariantId and a.GenotypeId are of type int.
I cannot figure out why it why it will not do the comparison. Is this a deferred execution issue? It doesn't seem like it should be...
Thanks in advance.
List<T>.Contains only takes a single parameter of type T. In your case, T is Int32 but you're passing in a Int32[].
If you want to check that both values are in the list, you have to break the calls apart:
where d.DrugId == drugId &&
variantGenotypeIds.Contains(a.VariantId) &&
variantGenotypeIds.Contains(a.GenotypeId)
EDIT
If variantGenotypeIds is actually a List<Int32[]>, then there's another issue. LINQ to SQL will try to convert your query into its SQL equivalent. In this case, there's no way to translate your query into SQL so LINQ to SQL will throw an Exception.
If you really need to query this way, you'll have to read the records into memory first and then query using LINQ to Objects (which may or may not be a big deal depending on how many rows you are reading):
var query =
from a in masterDB.tbl_thirty_second_summaries_multi_variant_associations
join d in masterDB.tbl_thirty_second_summaries_multi_variants
on a.ThirtySecSummaryId equals d.ThirtySecondSummaryId_this
where d.DrugId == drugId
select new { a, d }
var originalSummaryCandidates =
(from q in query.AsEnumerable()
where variantGenotypeIds.Contains(new [] { q.a.VariantId, q.a.GenotypeId})
select d.ThirtySecondSummaryId_this)
.Distinct()
.ToList();
Array comparison uses reference equality by default. It's possible that linq-to-sql just tries to translate that into SQL that compares the values, but you'd have to look at the generated SQL to be sure. Another option would be to use Any instead:
where d.DrugId == drugId &&
variantGenotypeIds.Any(v => v[0] == a.VariantId && v[1] == a.GenotypeId)
but I'm not sure if Linq-to-Sql will be able to translate that to the correct SQL either. Another option would be to project the List` to a > and then do a string comparison:
variantGenotypeStrings = variantGenotypeIds.Select(v => string.Format("{0}|{1}", v[0],v[1]);
var originalSummaryCandidates =
(from a in masterDB.tbl_thirty_second_summaries_multi_variant_associations
join d in masterDB.tbl_thirty_second_summaries_multi_variants on a.ThirtySecSummaryId equals d.ThirtySecondSummaryId_this
where d.DrugId == drugId &&
variantGenotypeStrings.Contains(string.Format("{0}|{1}", a.VariantId, a.GenotypeId))
select d.ThirtySecondSummaryId_this)
.Distinct()
.ToList();
select a.stakebuyinid , a.StakeBuyInValue from StakeBuyInByStakeCategories AS b
left join StakeBuyIns AS a on b.stakebuyinid = a.stakebuyinid
where b.GametypeId = 1 and b.StakeCategoryID = 3 and a.Currencyid = 1
above is my Simple SQL query i want to write in LINQ
I am using following LINQ query but Raise Error :- "The cast to value type 'Int32' failed because the materialized value is null. Either the result type's generic parameter or the query must use a nullable type."
var query = (from v in db.StakeBuyInByStakeCategories.Where(x => x.GameTypeId == gametypeid && x.StakeCategoryId == stakecategoryid)
join u in db.StakeBuyIns.Where(y => y.CurrencyId == currencyid)
on v.StakeBuyInId equals u.StakeBuyInId into Temp
from vus in Temp.DefaultIfEmpty()
select new {
vus.StakeBuyInId,
vus.StakeBuyInValue )
Assume
StakeBuyInByStakeCategoriesList as IEnumerable<StakeBuyInByStakeCategories>
and StakeBuyInsList as IEnumerable<StakeBuyIns>
(from b in StakeBuyInByStakeCategoriesList
from a in StakeBuyInsList
.Where(b.stakebuyinid equals a.stakebuyinid)
.DefaultIfEmpty()
.Where( b.GametypeId == 1 and b.StakeCategoryID == 3 and a.Currencyid == 1)
select new {Stakebuyinid=a.stakebuyinid, StakeBuyInValue=a.StakeBuyInValue}
The int in your model should be an int?, since nullable return values are possible.
Can someone convert this to C# LINQ for me please ??
SELECT *
FROM vf
LEFT JOIN dbvf
ON vf.sid =dbvf.sid
AND vf.cid =dbvf.cid
WHERE dbvf.sid IS NULL
Both vf and dbvf are List<T>. sid and cid are integers.
What I am trying to do is find items in vf that are missing in dbvf.
try this
var ret = from p1 in vf
join p2 in dbvf
on p1.sid equals p2.sid && p1.cid equals p2.cid into g
from p2 in g.DefaultIfEmpty()
where p2 == null
select new {vf=p1, dbvf=p2}
or this simple
vf.Except(dbvf);
something like below
from dbvf in dbvfs
from vf in vfs
where vf.sid == dbvf.sid && vf.cid == dbvf.cid
where dbvf.sid == null
select new { dbvf = dbvf, vf = vf}
Try something like this:
var query =
from v in vf
join d in dbvf
on new { v.sid, v.cid }
equals new { d.sid, d.cid } into gj
where !gj.Any()
select v;
As stated earlier, your purpose is to do an "except". I've answered how to do this with left-join semantics.
var query =
from v in vf
join d in dbvf
on new { v.sid, v.cid }
equals new { d.sid, d.cid } into gj
from d in gj.DefaultIfEmpty()
where d == null
select v;
The anonymous types used here appear to be black magic to the uninitiated. However, the compiler creates the anonymous types (actually it's just one type) with exactly two properties named sid and cid as well as providing implementations for Equals and GetHashCode that Join will use in its implementation. My choice of gj for the into clause is because introducing the into causes the compiler to do a GroupJoin instead of a regular Join call.
I can add to the query to get a similar feel to your SQL sample by adding a from d in gj.DefaultIfEmpty() clause that reinstates the d range variable previously hidden by the into clause. Now I can add the where d == null clause nearly reaching parity with the original SQL.
This anonymous type introduction is something you may need to use again if you ever want to do other operations such as group by both sid and cid.
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.