Last 6 Payments - entity-framework

I need to get the last six payments from a schema that consists of just
Contribution Id
DUE Date
Amount
The payments spread over 7 years and I need to get the most current last six payments only I thought this would do it it as it follows my sql
SELECT TOP 6 [ID]
,[customerInfo]
,[IVACODE]
,[Contribution]
,[DUE_DATE]
,[isActive]
,[isDeleted]
FROM [portal].[dbo].[tblPortalContributionSchedule]
where customerInfo='01F6B68B-6FC2-4F9D-B586-6934B8D6C979'
and DUE_DATE <='2016/09/26'
ORDER BY DUE_DATE DESC
Linq Version
List<tblPortalContributionSchedule> _contributions
= portalEntities.tblPortalContributionSchedules
.Where(a => a.customerInfo == _customerId
&& a.isDeleted == false
&& a.DUE_DATE <=Convert.ToDateTime("2016/09/26"))
.Take(6)
.OrderByDescending(o => o.DUE_DATE)
.ToList();
foreach (var contribution in _contributions)
{
AllPayments.Add(new Payments(contribution.ID, Convert.ToDecimal(contribution.Contribution), Convert.ToDateTime(contribution.DUE_DATE), false));
}
But its not producing the same results as per below
Sorry people i require the answer in linq i need to no is that the correct way of doing it i getting less than exepected
Edit 1
This is the query I have so far but I still am not getting the same results as my sql script
List<tblPortalContributionSchedule> _contributions =
portalEntities.tblPortalContributionSchedules.Where(a => a.customerInfo ==
_customerId && a.isDeleted == false && a.DUE_DATE
<=Convert.ToDateTime("2016/09/26")).OrderByDescending(o =>
o.DUE_DATE).Take(6).ToList();
Edit 2
To show the code that I showed in the video
public List<Payments> getAllPayments(Guid _customerId)
{
List<Payments> AllPayments = new List<Payments>();
List<tblPortalPayment> _payments = portalEntities.tblPortalPayments.Where(a => a.CustomerId == _customerId && a.isDeleted == false).ToList();
foreach (var payment in _payments)
{
AllPayments.Add(new Payments(payment.id, Convert.ToDecimal(payment.paymentDue), Convert.ToDateTime(payment.paymentDate), Convert.ToBoolean(payment.isinArrears)));
}
List<tblPortalContributionSchedule> _contributions = portalEntities.tblPortalContributionSchedules.Where(a => a.customerInfo == _customerId && a.isDeleted == false && a.DUE_DATE<= Convert.ToDateTime("2016/09/26")).OrderByDescending(o => o.DUE_DATE).Take(6).ToList();
foreach (var contribution in _contributions)
{
AllPayments.Add(new Payments(contribution.ID, Convert.ToDecimal(contribution.Contribution), Convert.ToDateTime(contribution.DUE_DATE), false));
}
var result = AllPayments.OrderByDescending(o => o.paymentDate).ToList();
return AllPayments.OrderByDescending(o => o.paymentDate).ToList();
}

You can try it as shown below and let us know the result.
var dueDateFilter = new DateTime(2016, 09, 26);
List<tblPortalContributionSchedule> _contributions =
portalEntities.tblPortalContributionSchedules
.Where(a => a.customerInfo == _customerId
&& a.isDeleted == false
&& a.DUE_DATE <= dueDateFilter)
.OrderByDescending(o => o.DUE_DATE)
.Take(6)
.ToList();

Try using this query
SELECT [ID],
[customerInfo],
[IVACODE],
[Contribution],
[DUE_DATE],
[isActive],
[isDeleted]
FROM [portal].[dbo].[tblPortalContributionSchedule]
where customerInfo='01F6B68B-6FC2-4F9D-B586-6934B8D6C979'
and ROWNUM <= 6
ORDER BY DUE_DATE DESC

Related

Convert SQL Command to lambda expression

If possible, please guide me how to convert my SQL command to lambda expression
select d.* from takcontractdet d where d.contractid=pubcontractid and d.personid in
(
select p.id from personel p where p.parentid=pubparentid)
)
Two query
var personelIds = Personels.Where(p => p.ParentId == pubparentid)
.Select(e => e.Id).ToList();
var result = Takcontractdets.Where(d => d.contractid == pubcontractid &&
personelIds.Contains(d.PersonId)).ToList();
One query
var result = Takcontractdets.Where(d => d.contractid == pubcontractid &&
Personels.Where(p => p.ParentId == pubparentid)
.Select(e => e.Id).ToList().Contains(d.PersonId))
.ToList();

Slow Include query with EF

Context: The webapplication is some sort of Reddit with Tags.
I have the following include initialisation which returns a IQueryable:
IQueryable<Item> items = itemRepository
.Include( //.Actions
el => el.Votes,
el => el.Comments,
el => el.CreatedBy.Roles,
el => el.TagItems.Select(dl => dl.Tag.Actions))
.Where(el => el.SiteId == siteId && el.Status >= 0)
.OrderBy(orderBy).AsNoTracking();
The IQueryable is later used with ExpressionBuilder (LinqKit), because there are a lot of AND / OR queries.
When i use the personal mode on my application ( = show only results that a user upvoted/created or results from the tags that the user is following), the query becomes really slow:
if (filterBy.PersonalMode)
{
// || el.TagItems.Any(dl => dl.Tag.UserId == filterBy.UserId)
itemPredicate = itemPredicate.And(el =>
el.Votes.Select(dl => new { UserId = dl.UserId}).Any(dl =>
dl.UserId == filterBy.UserId)
|| el.CreatedById == filterBy.UserId
|| (filterBy.RoleId.HasValue && el.TagItems.Select(dl => new { UserRoleId = dl.Tag.UserRoleId, PersonalTags = dl.Tag.PersonalTags }).Any(dl => dl.UserRoleId.HasValue && filterBy.RoleId.HasValue && dl.UserRoleId.Value == filterBy.RoleId.Value))
|| el.TagItems.Any(dl => dl.Tag.PersonalTags.Select(cl => new { UserId = cl.UserId }).Any(cl => cl.UserId == filterBy.UserId)));
}
I'm trying to stay away from alternatives from EF, because it keeps my code pretty clean to read.
The query itselve, mentions a 61% execution time.
Execution plan XML:
https://www.brentozar.com/pastetheplan/?id=ry9najEMr
Slow part:
Output list
[handlr].[dbo].[Tags].Id; [handlr].[dbo].[Tags].Name; [handlr].[dbo].[Tags].SiteId; [handlr].[dbo].[Tags].Active; [handlr].[dbo].[Tags].CreatedOn; [handlr].[dbo].[Tags].FillsInParentTag; [handlr].[dbo].[Tags].ShowOnOverview; [handlr].[dbo].[Tags].ParentTagId; [handlr].[dbo].[Tags].LeftBower; [handlr].[dbo].[Tags].RightBower; [handlr].[dbo].[Tags].Depth; [handlr].[dbo].[Tags].Caption; [handlr].[dbo].[Tags].isRestricted; [handlr].[dbo].[Tags].Description; [handlr].[dbo].[Tags].ShowTag; [handlr].[dbo].[Tags].Count; [handlr].[dbo].[Tags].UserId; [handlr].[dbo].[Tags].UserRoleId; [handlr].[dbo].[Tags].SynonymOfTagId
Visual:
Any advice on how to improve this query? Adding non-clustured indexes don't seem to do much currently.

Entity Framework Core: combining multiple result objects into one collection

I am facing this linq query for entity framework core (2.0).
var result = await dbContext.Table1DbSet
.Where(t1e => t1e.Id == id && t1e.Id2 == id2)
.Select
(
t1e =>
t1e.Table2NavPropICollection.Select
(
t2e => new
{
singleObject = t2e.Table3NavPropObject.TargetObject,
enumerable1 = t2e.Table3NavPropObject.Table4NavPropObject.Table5NavPropICollection.Select(t5e => t5e.TargetObject),
enumerable2 = t2e.Table3NavPropObject.Table6NavPropObject.Table7NavPropICollection.Select(t7e => t7e.TargetObject),
enumerable3 = t2e.Table3NavPropObject.Table8NavPropICollection.SelectMany(t8e => t8e.Table9NavPropICollection.Select(t9e => t9e.TargetObject))
}
)
)
.ToListAsync();
The goal is to query all the referenced instances of TargetObject which is referenced accros ~ 10 different tables.
Currently it returns an IEnumerable where the anonymous object contains the properties singleObject, enumerable1, enumerable2, enumerable3. All those properties are of type TargetObject or IEnumerable.
Can I, and how, rewrite the query to not return anonymous objects but just an IEnumerable containing all the values?
For some reason the compiler won't let me iterate over the anonymous collection and flatten it manually.
This should do the trick if you want one array per t1e row.
var result = await dbContext.Table1DbSet
.Where(t1e => t1e.Id == id && t1e.Id2 == id2)
.Select
(
t1e =>
t1e.Table2NavPropICollection.Select
(
t2e => new[] {t2e.Table3NavPropObject.TargetObject}.Concat(
t2e.Table3NavPropObject.Table4NavPropObject.Table5NavPropICollection.Select(t5e => t5e.TargetObject)).Concat(
t2e.Table3NavPropObject.Table6NavPropObject.Table7NavPropICollection.Select(t7e => t7e.TargetObject)).Concat(
t2e.Table3NavPropObject.Table8NavPropICollection.SelectMany(t8e => t8e.Table9NavPropICollection.Select(t9e => t9e.TargetObject)))
)
)
.ToListAsync();
If you want it completely flat, you'll want to switch that Select to a SelectMany().
var result = await dbContext.Table1DbSet
.Where(t1e => t1e.Id == id && t1e.Id2 == id2)
.SelectMany
(
t1e =>
t1e.Table2NavPropICollection.Select
(
t2e => new[] {t2e.Table3NavPropObject.TargetObject}.Concat(
t2e.Table3NavPropObject.Table4NavPropObject.Table5NavPropICollection.Select(t5e => t5e.TargetObject)).Concat(
t2e.Table3NavPropObject.Table6NavPropObject.Table7NavPropICollection.Select(t7e => t7e.TargetObject)).Concat(
t2e.Table3NavPropObject.Table8NavPropICollection.SelectMany(t8e => t8e.Table9NavPropICollection.Select(t9e => t9e.TargetObject)))
)
)
.ToListAsync();
Is Add and/or Concat a possible solution?
PoC:
var a = new [] { 1,2,3 };
var result = new {
firstA = a.First(),
otherAs = a,
backwards = a.Reverse()
};
var final = new List<int>();
final.Add(result.firstA);
final.Concat(result.otherAs.Concat(result.backwards))
.Dump();

How can I Include the related Entities but exclude the records where Deleted=true?

I have two Entities EntityTest and EntityRelated.
I want to query and get results from both Entites where Deleted is not true in both Entites.
I have tries below statement. It return EntityTest records by excluding records having Deleted = true but records of EntityRelated are not filtered.
db.EntityTest
.Include(i => i.EntityRelated)
.Where(x => x.Deleted != true && x.EntityRelated.Any(a => a.Deleted != true).ToList();
Solution 1: Use this implementation of an extension method Include2() Include2. as following:
db.EntityTest
.Include(i => i.EntityRelated.Where(e=>e.Deleted == false))
.Where(x => x.Deleted != true && x.EntityRelated.Any(a => a.Deleted != true)
.ToList();
Solution 1:

DBIx::Class query fails, yet dump from DBIC_TRACE works

I cannot rewrite the current DB schema right now BTW, but that's beside the point to the issue I've hit, so please ignore the table structure :D
I'm running this DB query:
my $rs = $dbx->resultset('Result')->search(
{
'result_hnd' => 16078055,
'seasons.outdoor' => 'venue.outdoors',
'seasons.start_date' => { '<=' => 'meet.date_end' },
'seasons.end_date' => { '>=' => 'meet.date_begin' },
},
{
'join' => [
{
'team' => {
'league_teams' => {
'league' => 'seasons',
},
},
},
{
'meet' => 'venue'
},
],
'+select' => ['seasons.season_hnd','seasons.name','seasons.start_date','seasons.end_date','meet.date_begin','meet.date_end'],
'+as' => ['season_hnd','season_name','s_start','s_end','m_start','m_end'],
columns => ['result_hnd'],
group_by => ['seasons.season_hnd'],
}
);
When I run this, I get no results. With DBIC_TRACE on, I see the generated SQL as:
SELECT me.result_hnd, seasons.season_hnd, seasons.name, seasons.start_date, seasons.end_date, meet.date_begin, meet.date_end FROM track.result me JOIN track.team team ON team.team_hnd = me.team_hnd LEFT JOIN track.league_team league_teams ON league_teams.team_hnd = team.team_hnd LEFT JOIN track.league league ON league.league_hnd = league_teams.league_hnd LEFT JOIN track.season seasons ON seasons.league_hnd = league.league_hnd OR seasons.league_hnd = league.parent_league_hnd JOIN track.meet meet ON meet.meet_hnd = me.meet_hnd JOIN track.venue venue ON venue.venue_hnd = meet.venue_hnd WHERE ( ( result_hnd = ? AND seasons.end_date >= ? AND seasons.outdoor = ? AND seasons.start_date <= ? ) ) GROUP BY seasons.season_hnd: '16078055', 'meet.date_begin', 'venue.outdoors', 'meet.date_end'
When I copy and paste this statement into my MYSQL client (and interpolate the placeholders), like this:
SELECT me.result_hnd, seasons.season_hnd, seasons.name, seasons.start_date, seasons.end_date, meet.date_begin, meet.date_end
FROM track.result me
JOIN track.team team ON team.team_hnd = me.team_hnd
LEFT JOIN track.league_team league_teams ON league_teams.team_hnd = team.team_hnd
LEFT JOIN track.league league ON league.league_hnd = league_teams.league_hnd
LEFT JOIN track.season seasons ON seasons.league_hnd = league.league_hnd OR seasons.league_hnd = league.parent_league_hnd
JOIN track.meet meet ON meet.meet_hnd = me.meet_hnd
JOIN track.venue venue ON venue.venue_hnd = meet.venue_hnd
WHERE ( ( result_hnd = 16078055 AND seasons.end_date >= meet.date_begin AND seasons.outdoor = venue.outdoors AND seasons.start_date <= meet.date_end ) )
GROUP BY season_hnd;
I get the exact result I expect (7 records).
This is really bizarre. To all intents and purposes, isn't that exactly the same query? Am I missing something in my debugging? Or is something else happening at the DBIx::Class::ResultSet layer that isn't being dumped?
To tell SQL::Abstract that the value on the right is actually an identifier, you can do the following (as outlined in the docs):
{
'result_hnd' => 16078055,
'seasons.outdoor' => { -ident => 'venue.outdoors' },
'seasons.start_date' => { '<=' => { -ident => 'meet.date_end' } },
'seasons.end_date' => { '>=' => { -ident => 'meet.date_begin' } },
},
To all intents and purposes, isn't that exactly the same query?
(For all intents and purposes, ...)
No. In the log, you have something equivalent to
result_hnd = '16078055'
AND seasons.end_date >= 'meet.date_begin'
AND seasons.outdoor = 'venue.outdoors'
AND seasons.start_date <= 'meet.date_end'
or maybe
result_hnd = 16078055
AND seasons.end_date >= 'meet.date_begin'
AND seasons.outdoor = 'venue.outdoors'
AND seasons.start_date <= 'meet.date_end'
In your attempt, you used
result_hnd = 16078055
AND seasons.end_date >= meet.date_begin
AND seasons.outdoor = venue.outdoors
AND seasons.start_date <= meet.date_end
Sorry, I don't have the solution for you.