Linq to Entities - Correlated Subquery - linq

I have the following query:
var query = db.DepoAccounts
.Join(db.DepoAccountDetails,
t1 => new { t1.INTEG_REF_NO, t1.BASE_DATE },
t2 => new { t2.INTEG_REF_NO, t2.BASE_DATE },
(t1, t2) => new DataCustomerAccountGDWHModel
{
BranchNumber = t1.BR_NO,
BookedBalance = t2.DP_FACE_BAL_VAL_ADJ,
}
)).Where(ac => ac.BranchNumber == "500" &&
(ac.AccountNumber.Substring(0, 1) == "H" ||
ac.AccountNumber.Substring(0, 1) == "F"));
How do I add to the above to do a correlated subquery?
AND DEP2.EFECT_DT = (SELECT MAX(DEP3.EFECT_DT) FROM
R_DBLNK_US.DW_TRN_DEPO_ACC_DTL_D DEP3
WHERE DEP.INTEG_REF_NO = DEP3.INTEG_REF_NO
AND DEP.BASE_DATE = DEP3.BASE_DATE)

Related

LINQ: Cannot get more than two Where clauses to work

I cannot get the following to work properly. I want to search my database using more than 2 conditions where it will be possible to search only on one, two or all three, thus narrowing the search. At the moment, I can only get it to work with one condition at a time, and it only evaluates the first condition when having more than 3.
How can I Include more than 2 conditions? I have tried several proposed solutions from other sources, that uses if statements and where clauses, but so far none of them have worked.
This is my controller
public IActionResult Index(string searchString, int searchProject, string searchTitel)
{
var Projektdokumenter = from p in _context.ProjekterDokutypeDokuundertype
.Include(p => p.Dokumenttype)
.Include(p => p.Dokuundertype)
.Include(p => p.Forfatter)
.Include(p => p.P)
.Include(p => p.Sprog)
select p;
if (!String.IsNullOrEmpty(searchString) ^ searchProject != null ^ !String.IsNullOrEmpty(searchTitel))
{
if (!String.IsNullOrEmpty(searchString))
{
var c = Projektdokumenter.Where(p => p.Forfatter.Initialer.Contains(searchString)).ToList();
return View(c);
}
{
if (searchProject != 0)
{
var d = Projektdokumenter.Where(p => p.P.ProjektId.Equals(searchProject)).ToList();
return View(d);
}
{
if(!String.IsNullOrEmpty(searchTitel))
{
var f = Projektdokumenter.Where(p => p.Titel.Contains(searchTitel)).ToList();
return View(f);
}
}
}
}
var e = Projektdokumenter.Where(c.Contains(searchString) && p.P.ProjektId.Equals(searchProject) && p.Titel.Contains(searchTitel)).ToList();
return View(e);
}
IQueryable can be combined, so just write in native way:
{
var query = _context.ProjekterDokutypeDokuundertype
.Include(p => p.Dokumenttype)
.Include(p => p.Dokuundertype)
.Include(p => p.Forfatter)
.Include(p => p.P)
.Include(p => p.Sprog)
.AsQueryable();
if (!string.IsNullOrEmpty(searchString))
{
query = query.Where(p => p.Forfatter.Initialer.Contains(searchString));
}
if (searchProject != 0)
{
query = query.Where(p => p.P.ProjektId == searchProject);
}
if (!string.IsNullOrEmpty(searchTitel))
{
query = query.Where(p => p.Titel.Contains(searchTitel))
}
return View(query.ToList());
}

Dynamic Bool Query for NEST (ElasticSearch)

Good day:
I'm trying to achieve a dynamic Bool Query. Example...
QueryContainer addressQuery = null;
QueryContainer typeQuery = null;
BoolQueryDescriptor <Facility> boolQuery = new BoolQueryDescriptor<Facility>();
QueryContainerDescriptor<Facility> sh = new QueryContainerDescriptor<Facility>();
SearchDescriptor<Facility> mainSh = new SearchDescriptor<Facility>();
if (search.searchTerm != null)
{
addressQuery = sh.Term(f => f.Address, search.searchTerm) ||
sh.Match(m => m.Field(f => f.Address).Query(search.searchTerm) ) ||
sh.Term(f => f.ZipCode, search.searchTerm) ||
sh.Match(m => m.Field(f => f.State).Query(search.searchTerm));
boolQuery = boolQuery.Should(b => addressQuery);
}
if (search.type != null) {
typeQuery = sh.Term(f => f.Types.First(), search.type);
boolQuery = boolQuery.Must(b => typeQuery && addressQuery);
}
if (boolQuery != null)
{
mainSh = mainSh.Query(q => q.Bool(b => boolQuery));
request = await this._elasticClient.SearchAsync<Facility>(s => mainSh.Size(search.size));
}
This query is turning into a OR between AddressQuery and TypeQuery however, I'd like to achieve an And condition between both query. Effectively making the query dynamic. Is this possible? Example: dynamic addressQuery && typeQuery.
Thanks.
Fire it out..you can && or || query containers...sorter like:
queryContainer1=queryContainer1 && queryContainer2
Then .bool(b => b(queryContainer1)).

Linq to sql - nested select with groupby

I have the following SQL query:
SELECT * FROM [dbo].[Bil_Audit_BillingParameter] WHERE ([Status4Eyes]!='APPROVED' OR [Status4Eyes] IS NULL )AND
[LastComment] != '' AND
(Service='EUR' OR Service='S1') AND
[AudId] IN (SELECT MAX([AudId])
FROM [Bil_Audit_BillingParameter]
GROUP BY ID) UNION SELECT * FROM
[dbo].Bil_Audit_BillingParameter] WHERE ([Status4Eyes]!='APPROVED' OR [Status4Eyes] IS NULL) AND
[LastComment] != '' AND
(Service='EUR' OR Service='S1') AND
[AudId] IN (SELECT MIN([AudId])
FROM [Bil_Audit_BillingParameter]
GROUP BY ID)
How it is converting to linq? I tried the following , but ends up with error.
public IQueryable<ParameterUpdates> Get(ODataQueryOptions op)
{
var audIdMax = db.ParameterUpdates.GroupBy(x => x.ID).Select(v => v.Max(x => x.AudId));
var audIdMin = db.ParameterUpdates.GroupBy(x => x.ID).Select(a => a.Min(x => x.AudId));
var results1 = db.ParameterUpdates.Where(p => (!p.Status4Eyes.Contains("Approved") || string.IsNullOrEmpty(p.Status4Eyes)) &&
!p.LastComment.Contains("NULL") &&
(p.Service.Contains("EUR") || p.Service.Contains("S1")) &&
p.AudId.Equals(audIdMax));
var results2 = db.ParameterUpdates.Where(p => (!p.Status4Eyes.Contains("Approved") || string.IsNullOrEmpty(p.Status4Eyes)) &&
!p.LastComment.Contains("NULL") &&
(p.Service.Contains("EUR") || p.Service.Contains("S1")) &&
p.AudId.Equals(audIdMin));
var results = results1.Union(results2);
return results.AsQueryable();
}
Could anyone please help.
You can try this, first group by id create the filter output. Then inner join the filter with max or min audit id with the actual table and find the result.
var filter = ParameterUpdate.Where(p => (p.status == "Approved" || p.status == null)
&& p.lastComment != ""
&&(p.service=="EUR" || p.service=="S1")).GroupBy(p => p.id);
var result = (from p in ParameterUpdate
from f in filter
where p.auditId == f.Min(m => m.auditId) ||
p.auditId == f.Max(m => m.auditId)
select p);
public IQueryable<ParameterUpdates> Get()
{
var groupMax = db.ParameterUpdates
.GroupBy(u => u.ID)
.Select(grp => grp.Max(x => x.AudId));
var groupMin = db.ParameterUpdates
.GroupBy(u => u.ID)
.Select(grp => grp.Min(x => x.AudId));
var results = (db.ParameterUpdates.
Where(r => (r.Status4Eyes != "APPROVED" || r.Status4Eyes == null) &&
(r.LastComment != null) &&
(r.Service == "EUR" || r.Service == "S1") &&
(groupMax.Contains(r.AudId) || groupMin.Contains(r.AudId))
)).ToList();
return results.AsQueryable();

How to get EF Framework to generate this group by query

I tried a few different ways and I am not impressed with the generated output query. It seems so inefficient. It needs to be efficient and shouldn't bring back all the rows into the app layer
select year(datetaken) as yr,
month(datetaken) as mth,
day(datetaken) as dy,
count(*) as totalpics
from photos
where photos.dateTaken <= #cutoffdate
group by year(datetaken), month(datetaken), day(datetaken)
order by yr asc, mth asc, dy asc
LINQ query:
var query = ctx.Photos.Where(p => p.DateTaken <= maxCutOffDate)
.GroupBy(p => new { p.DateTaken.Year, p.DateTaken.Month, p.DateTaken.Day })
.Select(grp => grp);
var results = query.ToList();
Select only the grouping key (grp.Key):
var query = ctx.Photos.Where(p => p.DateTaken <= maxCutOffDate)
.GroupBy(p => new { p.DateTaken.Year, p.DateTaken.Month, p.DateTaken.Day })
.Select(grp => grp.Key);
var results = query.ToList();
Edit
Or, including the count of totalpics:
var query = ctx.Photos.Where(p => p.DateTaken <= maxCutOffDate)
.GroupBy(p => new { p.DateTaken.Year, p.DateTaken.Month, p.DateTaken.Day })
.Select(grp => new
{
Date = grp.Key,
TotalPics = grp.Count()
});
var results = query.ToList();
You can access the key properties through grp.Key and the count through grp.Count().
var query = ctx.Photos.Where(p => p.DateTaken <= maxCutOffDate)
.GroupBy(p => new { p.DateTaken.Year, p.DateTaken.Month, p.DateTaken.Day })
.Select(grp => new
{
grp.Key.Year,
grp.Key.Month,
grp.Key.Day,
Count = grp.Count()
});
var results = query.ToList();

LINQ lambda expression for many-to-one inner join involving max()

I have the following schema:
Table1
ID int
Table2
ID int
Table1ID int
Datetime datetime
Table3
ID int
Table2ID int
Name varchar(255)
All columns are not null. How do I write the following SQL query in LINQ using lambda expressions?
select Table1.*
from Table2
inner join (
select Table1ID, max(Datetime) as Datetime
from Table2
group by Table1ID
) a on Table2.Table1ID = a.Table1ID and Table2.Datetime = a.Datetime
inner join Table3 on Table2.ID = Table3.Table2ID
inner join Table1 on Table1.ID = Table2.Table1ID
where Name = 'me'
EDIT:
I am using LINQ to EF. I have tried
var myEntities = new MyEntities();
var a = myEntities.Table2.Select(x => new { x.Id, x.Datetime }).GroupBy(x => x.Id).Select(x => new { Id = x.Key, Datetime = x.Max(y => y.Datetime) });
var b = myEntities.Table2.Join(a.ToList(), x => new { Id = x.Table1Id, x.Datetime }, y => new { y.Id, y.Datetime }, (x, y) => x.Id);
return myEntities.Table3.Where(x => x.Name == "me" && b.Contains(x.Table2Id)).Select(x => x.Table2.Table1).ToList();
but it comes back with
System.NotSupportedException: Unable to create a constant value of type 'Anonymous type'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.
highlighting the last line above. The stack trace shows it is ToList() throwing this exception.
I figured it out; it was that
var b = myEntities.Table2.Join(a.ToList(),
should be
var b = myEntities.Table2.Join(a,
Also, the query should be
var myEntities = new MyEntities();
var a = myEntities.Table2.Select(x => new { x.Table1Id, x.Datetime }).GroupBy(x => x.Table1Id).Select(x => new { Table1Id = x.Key, Datetime = x.Max(y => y.Datetime) });
var b = myEntities.Table2.Join(a, x => new { x.Table1Id, x.Datetime }, y => new { y.Table1Id, y.Datetime }, (x, y) => x);
return b.Join(myEntities.Table3, x => x.Id, y => y.Table2Id, (x, y) => new { x.Table1, y.Name }).Where(x => x.Name == "me").Select(x => x.Table1).ToList();

Resources