LINQ to SQL Query using all memory before timing out - vb.net

Hi I have a stored procedure within SQL that is a simple select with multiple inner joins, I converted this stored procedure to LINQ and when executing the memory usage climbs until I get out of memory exceptions. I am definitely new to LINQ so I am hoping it is just the way I am doing things. Below is the LINQ code
EDIT: StockRoomID, CustomerID (integers)
StartDate, EndDate (datetime)
variable passed into the function
Dim query = (From prds In context.prds
Join prd_colour In context.prd_colours On prd_colour.prd_id Equals prds.prd_id
Join prd_colour_srsp In context.prd_colour_srsps On prd_colour.prd_colour_id Equals prd_colour_srsp.prd_colour_id
Join prd_br In context.prd_brs On prd_br.prd_colour_id Equals prd_colour.prd_colour_id
Join prd_stk_rm In context.prd_stk_rms On prd_stk_rm.prd_br_id Equals prd_br.prd_br_id
Join ct_colour In context.ct_colours On ct_colour.ct_colour_id Equals prd_colour.ct_colour_id
Join ct_pmg In context.ct_pmgs On ct_pmg.ct_pmg_id Equals prds.ct_pmg_id
Join ct_pmg_detail In context.ct_pmg_details On ct_pmg_detail.ct_pmg_id Equals ct_pmg.ct_pmg_id
Join ct_stk_rm In context.ct_stk_rms On ct_stk_rm.ct_br_id Equals ct_pmg_detail.ct_br_id And ct_stk_rm.ct_stk_rm_id Equals prd_stk_rm.ct_stk_rm_id
Join ct_cust_type In context.ct_cust_types On ct_cust_type.ct_cust_type_id Equals ct_pmg_detail.ct_cust_type_id
Join ct_cust_br In context.ct_cust_brs On ct_cust_br.ct_cust_type_id Equals ct_cust_type.ct_cust_type_id
Where prds.prd_invisible_yn = 0 And prds.sell_yn = 1 And prds.ct_apg_id = 3 And ct_stk_rm.ct_stk_rm_id = StockRoomID And _
ct_cust_br.ct_cust_id = CustomerID And prd_colour_srsp.srsp_date_beg <= StartDate And prd_colour_srsp.srsp_date_end >= EndDate Or _
prd_colour_srsp.srsp_date_end Is Nothing And ct_pmg_detail.pmg_date_beg <= StartDate And ct_pmg_detail.pmg_date_end >= EndDate Or _
ct_pmg_detail.pmg_date_end Is Nothing
Select New prd_colour_mix With {.pid = prd_colour.prd_colour_id, .prdcode = prds.prd_sbcode & "-" & ct_colour.ct_colour_code, .prddesc = prds.prd_desc & "-" & ct_colour.ct_colour_desc, .prdLegacyCode = prd_colour.prd_legacy_code}).ToList
This query should return roughly 7k records, the stored procedure takes about 500ms to execute
Thanks

Most likely it is doing client side something that you want it to do serverside.
Download LINQPad (free), fire it up and add connection to your datasource, select the added datasource as the active one for your query, set Language to "VB Statements" and then run it. Select the "SQL" tab in the result output window and inspect the SQL. Then you'll see what parts of the expression that is handled server side.

Related

using criteria in an update query involving a join

I'm using MS Access
The SQL below updates the CurrNumTees field in the Parent tblContact records with the number of tblTorTee records that have an end date (which is not the ultimate effect I am aiming for, but I provide it as a starting point.
UPDATE tblContact
INNER JOIN tblTorTee ON tblContact.ContactId = tblTorTee.TorId
SET tblContact!CurNumTees = DCount("[tblTorTee.EndDate]",
"tbltortee","Torid = " & [ContactId]);
I need to update the CurrNumTees field with the number of records in tblTorTee that do not have an EndDate, in other words, that field is blank. I’ve tried using WHERE and HAVING and IS NULL in various combinations and locations, but without success. Could you help point me in the right direction?
The MS Access COUNT function does not count nulls, so I think you have to do this in two stages.
Firstly create a query like this:
SELECT TorId, IIF(ISNULL(EndDate),1,0) AS isN
FROM tblTorTee
WHERE EndDate IS NULL;
And save it as QryEndDateNull
Now you can run an Update Query like this:
UPDATE tblContact
SET tblContact.CurNumTees = DSUM("IsN","QryEndDateNull","TorId = " & [ContactID]);
Saving calculated data (data dependent on other data) is usually a bad design, especially aggregate data. Should just calculate when needed.
Did you try the IS NULL criteria within the DCount()?
UPDATE tblContact Set CurNumTees = DCount("*", "tblTorTee", "EndDate Is Null AND TorId = " & [ContactId]);

Count instances of consecutive dates for associated name (VBA, SQL)

Good morning all,
I am trying to determine instances of consecutive dates (excluding Sunday) from a data set. The data is stored in Access and I am pulling the required dates into Excel. I am then trying to determine how many instances each person has in the data provided. Example below.
Data example:
| Name | Date of absence|
| Bob | 02/01/17 |
| Jill | 02/01/17 |
| Bob | 03/01/17 |
| Jill | 04/01/17 |
Result example:
Bob - 1 Instance, 2 days
Jill - 2 Instance, 2 days
I started trying to work through this with VBA in Excel using loops to rotate through each instance of absence until all people had been completed/ticked off, however the code was becoming really cumbersome and it felt very inefficient, not to mention how slow it was getting for larger data sets! I wonder if it is possible to query the database for the info or to write something a bit more efficient.
Any help or suggestions would be appreciated!
Update:
Testing Tom's suggestion;
Sql = "SELECT Absence.Racf,count(RecordDate) as dups"
Sql = Sql & " FROM Absence"
Sql = Sql & " left outer join"
Sql = Sql & " (select Racf, [RecordDate]+IIf(Weekday([RecordDate],7)=1,2,1) as date1 from Absence) t1"
Sql = Sql & " on Absence.RecordDate=t1.date1 and Absence.Racf=t1.Racf"
Sql = Sql & " where date1 Is Not Null"
Sql = Sql & " group by Absence.Racf"
But unfortunately on the list of dates below it returns 7, instead of 5.
Dates:
23-Feb-16,24-Feb-16,08-Aug-16,09-Aug-16,10-Aug-16,31-Aug-16,24-Oct-16,25-Oct-16,26-Oct-16,25-Jan-17,26-Jan-17,27-Jan-17
So this is how the SQL might actually look in an Access query
SELECT table1.name,count(date) as dups
FROM Table1
left outer join
(select name, [date]+IIf(Weekday([Date],7)=1,2,1) as date1 from table1) t1
on table1.date=t1.date1 and table1.name=t1.name
where date1 is not null
group by table1.name
;
If you want to run this from Excel using a macro, here is a useful reference.
I lifted the code from there and changed the lines which set up the SQL query string to
SQL = "SELECT table1.name,count(date) as dups"
SQL = SQL & " FROM table1"
SQL = SQL & " left outer join"
SQL = SQL & " (select name, [date]+IIf(Weekday([Date],7)=1,2,1) as date1 from table1) t1"
SQL = SQL & " on table1.date=t1.date1 and table1.name=t1.name"
SQL = SQL & " where date1 Is Not Null"
SQL = SQL & " group by table1.name"
and it worked fine.
Try this if you want to get sequences with length greater than one
SELECT Absence.Racf, Count(Absence.RecordDate) AS CountOfRecordDate
FROM (Absence LEFT JOIN (select Racf, RecordDate+IIf(Weekday([RecordDate],7)=1,2,1) as RecordDate1 from Absence) AS t1 ON (Absence.RecordDate = t1.RecordDate1) AND (Absence.Racf = t1.Racf))
LEFT JOIN (select Racf, [RecordDate]-IIf(Weekday([RecordDate],2)=1,2,1) as RecordDate2 from Absence) AS t2 ON (Absence.RecordDate = t2.RecordDate2) AND (Absence.Racf = t2.Racf)
WHERE (((t1.RecordDate1) Is Not Null) AND ((t2.RecordDate2) Is Null))
GROUP BY Absence.Racf;
Or this if you want to get sequences of one or more consecutive dates
SELECT Absence.Racf, Count(Absence.RecordDate) AS CountOfRecordDate
FROM Absence LEFT JOIN (select Racf, [RecordDate]+IIf(Weekday([RecordDate],7)=1,2,1) as RecordDate2 from Absence) AS t2 ON (Absence.RecordDate = t2.RecordDate2) AND (Absence.Racf = t2.Racf)
WHERE (((t2.RecordDate2) Is Null))
GROUP BY Absence.Racf;
adding to the SQL string as before.
This can be done using array formula in Excel. In D I have =INDEX($A2:$A$15,MATCH(0,COUNTIF($D$1:$D1,$A2:$A$15),0)) to get the unique employees, then in E I have the following to count the instances =SUM(--(($A$1:$A$15=D1)*(OFFSET($A$1:$A$15,1,0)=D1)*(OFFSET($B$1:$B$15,1,0)-$B$1:$B$15)=1)) which gives the result something like this. You'll need to add another criteria, based on weekday (I will adjust a little later as running low on time) This relies on the data being in date order
EDIT : I understand this is not the full answer and will require modification, a starting point :o)
Covering the Sunday absence (will still need weekday check):
=D1 & " " & COUNTIF($A$1:$A$15,D1) &" instances " & SUM(--(--($A$1:$A$15=D1)*--(OFFSET($A$1:$A$15,1,0)=D1))*--(--(OFFSET($B$1:$B$15,1,0)-$B$1:$B$15=1)+--(OFFSET($B$1:$B$15,1,0)-$B$1:$B$15=2)))&" Consecutive"
Checking the weekday also
=D2 & " " & COUNTIF($A$1:$A$15,D2) &" instances " & SUM(--(--($A$1:$A$15=D2)*--(OFFSET($A$1:$A$15,1,0)=D2))*--(--(OFFSET($B$1:$B$15,1,0)-$B$1:$B$15=1)+--(WEEKDAY(OFFSET($B$1:$B$15,1,0),2)=1)*((OFFSET($B$1:$B$15,1,0)-$B$1:$B$15=2)))) & " Consecutive"
A SQL approach would be something along the lines of, based on a table 000Absence, which is the data from examples EEName and AbsDate.
SELECT abs1.EEName, abs1.AbsDate,
(select count(abs2.EEName) from 000Absence as abs2 where abs2.[EEName]=abs1.[EEName]) AS INSTANCES,
(select count(abs3.EEName) from 000Absence as abs3 where abs3.[EEName]=abs1.[EEName] and abs3.[AbsDate]=abs1.[AbsDate]+iif(weekday(abs3.[AbsDate],7)=1,2,1)) AS CONSECUTIVE
FROM 000Absence AS abs1;
Where the output can be got from the query, grouping by Employee etc.

NHibernate: Join a subquery (uses aggregation) with a table

I have a table containing records of machine movements between multiple locations.
As I only show the latest of them in a list, i have read only the data rows with the latest record date per machine until now in sql.
Select *
From records
INNER JOIN
(Select max(processdate) as maxDate, machinetag, machineno
from records
group by machinetag, machineno ) as lrcd
on records.machineTag = lrcd.machineTag and records.machineno = lrcd.machineno
and records.processDate = lrcd.maxDate
I have read many posts but I did not find any solution.
How can I implement this scenario with queryover?
Thany you very much in advance.
Sascha
Inner joins can almost always be rewritten as a combination of a where clauses and projections.
Something like this (I'm writing without a compiler, sorry if there are any mistakes):
Select
records.*,
(select max(processdate) as maxdate
from records
where lrcd.machineno = records.machineno)
-- add more projections if you need them
From records
where records.processDate =
(select max(processdate) as maxDate
from records
where lrcd.machineno = records.machineno) as lrcd
This should be easy to implement with QueryOver now (subqueries can be implemented in projections or restrictions).
Don't worry about the duplicated code - the query plan will optimise it for you.
Now I can offer a (probably) working solution:
Dim r As Record = Nothing
Dim subquery = QueryOver.Of(Of Record)() _
.Where(Function(rec) rec.R_MachineTag = r.R_MachineTag) _
.And(Function(rec) rec.R_MachineNo = r.R_MachineNo) _
.Select(Projections.Max(Of Record)(Function(rec) rec.R_ProcessDate)).Take(1)
Dim query = session.QueryOver(Function() r) _
.WithSubquery.WhereProperty(Function(rec) rec.R_ProcessDate).Eq(subquery) _
.List()
Thanks to cbp for giving me the hint ;)
This statement represents my statement without inner joins:
Select r.*
from records as r
where r.processDate =
(Select max(processdate) as maxDate
from records as lr
where lr.machinetag = r.machinetag and
lr.machineno = r.machineno)

MS Access SQL: Enumerate results from a many-to-one relationship

Very simply, I have a many-to-one relationship table set in MS Access where I've managed to pull out the distinct values as separate rows. I now need to enumerate these rows.
The query looks like the following (generated by the MS Access Designer - apologies for the formatting):
SELECT DISTINCT ValidationRule.ValidationCode AS Rule, Table.Template AS Template
FROM ValidationRule RIGHT JOIN (([Table] INNER JOIN TableVersion ON Table.TableID = TableVersion.TableID) INNER JOIN ValidationScope ON TableVersion.TableVID = ValidationScope.TableVID) ON ValidationRule.ValidationId = ValidationScope.ValidationID
GROUP BY ValidationRule.ValidationCode, Table.Template
ORDER BY ValidationRule.ValidationCode;
So my data looks like:
Rule Template
v0007_m C 00.01
v0189_h C 01.00
v0189_h C 05.01
v3000_i C 08.00
I need to add sequential values to the results as follows:
Rule Template Sequence
v0007_m C 00.01 1
v0189_h C 01.00 1
v0189_h C 05.01 2
v3000_i C 08.00 1
What function should I be looking at in MS Access SQL to do this?
If you save the query you have as a separate query called qryValdationRule, this query which builds off that should give you what you need:
SELECT qryValidationRule.Rule, qryValidationRule.Template, DCount("*", 'qryValidationRule', "[Rule] = '" & qryValidationRule.Rule & "' AND [Template] <= '" & qryValidationRule.Template & "'") AS Sequence
FROM qryValidationRule
ORDER BY qryValidationRule.Rule, qryValidationRule.Template;
We are looking up and getting a count of all records with the same Rule value with an equal or less Template value within the dataset. This, essentially, gives us a Sequence grouped by Rule. This only works properly if Template values are distinct across Rule groups, which should be the case because you are pulling a DISTINCT across the CROSS JOIN of tables. It is not as convenient or flexible as window functions, but will get you what you need.
You may also want to try this method, which may be more efficient:
SELECT t1.Rule, t1.Template, COUNT(t2.Template) AS Sequence
FROM qryValidationRule AS t1 INNER JOIN qryValidationRule AS t2 ON t1.Rule = t2.Rule AND t1.Template >= t2.Template
GROUP BY t1.Rule, t1.Template
ORDER BY t1.Rule, t1.Template;
EDIT: Added an alternative way to find the same data; may be more performant because of JOINing vs. subqueries.
Use: Count(*) AS Sequence
SELECT DISTINCT ValidationRule.ValidationCode AS Rule, Table.Template AS Template, Count(*) AS Sequence
FROM ValidationRule RIGHT JOIN (([Table] INNER JOIN TableVersion ON Table.TableID = TableVersion.TableID) INNER JOIN ValidationScope ON TableVersion.TableVID = ValidationScope.TableVID) ON ValidationRule.ValidationId = ValidationScope.ValidationID
GROUP BY ValidationRule.ValidationCode, Table.Template
ORDER BY ValidationRule.ValidationCode;

VB.NET LINQ to XML Left Join with ambiguous column name

I need to write a LINQ TO XML query, which queries two XML files exported from Access database tables. The original Access DB query looks like this:
SELECT
(
[TableB].[Code] Is Null,[TableA].[Code],
LCase(Left([TableA].[Code],1)) & ":" & [TableB].[code]
) AS Code,
Trim
(
[TableB].[Description] & " " & [TableA].[Description]
) AS Description
FROM TableA LEFT JOIN TableB
ON TableA.Code = TableB.SubProduct;
When I convert it to LINQ to XML, I have the problem of the right part of the left join is not available. My LINQ look like this:
Dim results = _
From a In TableA.Descendants("Product")
Group Join b In TableB.Descendants("Product")
On a.Element("Code").Value Equals b.Element("SubProduct").Value Into leftJoinGroup Group
From p In leftJoinGroup.DefaultIfEmpty
Select New With
{
I DON KNOW HOW TO WRITE IT
}
Both tables have the column named "Code". However, the variable TableB seems to be unavailable inside my Selectclause. I only have a and p available so I can't get the Code from TableB (b). How should I do that?
I just started using linq myself and ran into this issue last week. This was very helpful for me http://msdn.microsoft.com/en-us/vstudio/bb688088.aspx but here is an example of how to perform a left outer join in vb.net http://msdn.microsoft.com/en-us/vstudio/bb737909#lojoin.
In your example tableB is being stored into leftJoinGroup which your selecting from using p. To get values from tableB you will need to select from p and since your trying to concatenate the columns from both tableA and tableB, I would check if tableB record is null.
Dim results = From a In TableA.Descendants("Product") Group Join b In TableB.Descendants("Product") _
On a.Element("Code").Value Equals b.Element("SubProduct").Value Into leftJoinGroup = Group _
From p In leftJoinGroup.DefaultIfEmpty() _
Select New With { _
.Code = If(p Is Nothing, a.Element("Code").Value, String.Format("{0}:{1}", Left(a.Element("Code").Value.ToLower(), 1), p.Element("Code").Value)), _
.Description = If(p Is Nothing, a.Element("Description").Value, String.Format("{0} {1}", p.Element("Description").Value, a.Element("Description").Value))}
Here is an example of your code above, I didn't tested it. I've used this code when joining datatables not xdocuments. Sorry if this isn't clear this my first post here.