Entity framework vb.net error in translating query - sql

I am trying to convert this query:
select sales.TTL_Sales_Net, sales.TTL_Sales_Target, units.TTL_Units_Net
from epos_Anal_Branch_Sales_Day sales
join epos_PULL_PM_SKU_STATUS till on sales.BRANCH_ID = till.BRANCH_ID
join epos_Anal_Branch_Units_Day units on sales.BRANCH_ID = units.BRANCH_ID
where till.BRANCH_ID = 45 and sales.DATEKEY = 20140725 and units.DATEKEY = 20140725
from SQL into an Entity Framework query in VB.net. I am sending in the BRANCH_ID in my function and producing the datekey like so:
Dim MyDate As String = Date.Now.ToString("yyyyMMdd")
This is what I have but it just returns no results and I am at a complete loss as to why! This is my query thus far, if anyone can spot what I have done wrong then I would be grateful for a push in the right direction
Public Class clsStoreSales
Public Property DailyAmount As String
Public Property DailyUnits As String
Public Property SalesTarget As String
Public Property ErrorMessages As String
Public Shared Function GetStoreSales(ByVal BranchID As String) As List(Of clsStoreSales)
Dim live As New RMISEntitiesLive
Dim MyDate As String = Date.Now.ToString("yyyyMMdd")
Dim l As New List(Of clsStoreSales)
Try
Dim r = From till In live.epos_PULL_PM_SKU_STATUS
Join sales In live.epos_Anal_Branch_Sales_Day On till.BRANCH_ID Equals sales.BRANCH_ID
Join units In live.epos_Anal_Branch_Units_Day On till.BRANCH_ID Equals units.DATEKEY
Where till.BRANCH_ID = CDbl(BranchID) AndAlso sales.DATEKEY = CDbl(MyDate) AndAlso units.DATEKEY = CDbl(MyDate)
Select New With {.SalesAmount = sales.TTL_Sales_Net, .SalesTarget = sales.TTL_Sales_Target, .SaleUnits = units.TTL_Units_Net}
For Each t In r
Dim m As New clsStoreSales
m.DailyAmount = CStr(t.SalesAmount)
m.DailyUnits = CStr(t.SaleUnits)
m.SalesTarget = CStr(t.SalesTarget)
l.Add(m)
Next
Return l
Catch ex As Exception
Dim e As New clsStoreSales
e.ErrorMessages = ex.ToString
l.Add(e)
Return l
End Try
End Function
End Class
This is what sqlServer Profiler is showing as the query being run:
exec sp_executesql N'SELECT
[Extent1].[BRANCH_ID] AS [BRANCH_ID],
[Extent2].[TTL_Sales_Net] AS [TTL_Sales_Net],
[Extent2].[TTL_Sales_Target] AS [TTL_Sales_Target],
[Extent3].[TTL_Units_Net] AS [TTL_Units_Net]
FROM [dbo].[epos_PULL_PM_SKU_STATUS] AS [Extent1]
INNER JOIN [dbo].[epos_Anal_Branch_Sales_Day] AS [Extent2] ON [Extent1].[BRANCH_ID] = [Extent2].[BRANCH_ID]
INNER JOIN [dbo].[epos_Anal_Branch_Units_Day] AS [Extent3] ON [Extent1].[BRANCH_ID] = [Extent3].[DATEKEY]
WHERE ( CAST( [Extent1].[BRANCH_ID] AS float) = #p__linq__0) AND ( CAST( [Extent2].[DATEKEY] AS float) = #p__linq__1) AND ( CAST( [Extent3].[DATEKEY] AS float) = #p__linq__2)',N'#p__linq__0 float,#p__linq__1 float,#p__linq__2 float',#p__linq__0=45,#p__linq__1=20140725,#p__linq__2=20140725

This
Join units In live.epos_Anal_Branch_Units_Day On till.BRANCH_ID Equals units.DATEKEY
Should be this!
Join units In live.epos_Anal_Branch_Units_Day On till.BRANCH_ID Equals units.BRANCH_ID

Related

Why is this dropdown not populating?

I have three dropdowns; the second one (Members) populates based on what's in the first (Units), and the third one (Customers) SHOULD populate based on what's in the second; but it doesn't.
Here's the query that works in LINQPad (returns a list of Company names):
select distinct companyname from customers C left join members M on M.MemberNo = C.MemberNo where M.MemberNo = '052' order by companyname
...but does not work in the following code:
'Populate the Members dropdown
Dim selectedUnit As String = DropDownListUnits.Text
Dim membersDT As DataTable
sql = "select distinct shortname, M.memberno from members M left join memberunitproducts mup on M.MemberNo = mup.MemberNo where unit = '" + selectedUnit + "' order by shortname"
retDS = sqlDAL.runSQLDataSet(sql)
membersDT = retDS.Tables(0)
DropDownListMembers.DataSource = membersDT
DropDownListMembers.DataTextField = "shortname"
DropDownListMembers.DataValueField = "memberno"
DropDownListMembers.DataBind()
'Populate the Customers dropdown
Dim selectedMember As String = DropDownListMembers.DataValueField
Dim customersDT As DataTable
sql = "select distinct companyname from customers C left join members M on M.MemberNo = C.MemberNo where M.MemberNo = '" + selectedMember + "' order by companyname"
retDS = sqlDAL.runSQLDataSet(sql)
customersDT = retDS.Tables(0)
DropDownListCustomers.DataSource = customersDT
DropDownListCustomers.DataTextField = "companyname"
DropDownListCustomers.DataValueField = "companyname"
DropDownListCustomers.DataBind()
The third (Customers) dropdown remains unpopulated when this runs - why?
It's probably not needed, but here is the code for the first ("Units") dropdown:
'Populate the Units dropdown
Dim unitsDT As DataTable
sql = "Select distinct unit from masterunits where abs(active) = 1"
retDS = sqlDAL.runSQLDataSet(sql)
unitsDT = retDS.Tables(0)
DropDownListUnits.DataSource = unitsDT
DropDownListUnits.DataTextField = "unit"
DropDownListUnits.DataValueField = "unit"
DropDownListUnits.DataBind()
What am I missing or doing wrong?
I had to change this:
Dim selectedMember As String = DropDownListMembers.DataValueField
...to this:
Dim selectedMember As String = DropDownListMembers.SelectedItem.Value

mscorlib error on LINQ

I am getting an InvalidOperation on mscorlib.dll error on the following query and cannot for the life of me figure out why.
Here is the Class I'm populating the List(Of ) with;
Public Class ProjectionPerformance
Public SymbolId As Long
Public Name As String
Public ProjectionDate As String
Public ActualRange As Double
Public ProjectedRange As Double
End Class
Those types match the types in the table except for the date which I convert to a string
Here is the function with the LINQ query
Public Shared Function GetRangeProjectionPerformance(Optional daysToRetrieve As Integer = 100) As Dictionary(Of Long, List(Of ProjectionPerformance))
Dim todaysDate As Date = DateTime.Now.Date
Dim lookbackDate As Date = todaysDate.AddDays(daysToRetrieve * -1)
Using ctx As New ProjectionsEntities
Dim query = (From d In ctx.projections
Where d.SymbolId <= 42 AndAlso d.Date >= lookbackDate
Join t In ctx.symbols On d.SymbolId Equals t.Id
Let actualRange = d.ActualHigh - d.ActualLow
Let projectedRange = d.HighProjection - d.LowProjection
Select New With {
d.Date,
d.SymbolId,
t.Name,
projectedRange,
actualRange}).GroupBy(Function(o) o.SymbolId).ToDictionary(Function(p) p.Key,
Function(x) x.Select(Function(y) New ProjectionPerformance() With {
.SymbolId = y.SymbolId,
.ProjectionDate = y.Date.ToString(),
.Name = y.Name,
.ActualRange = y.actualRange,
.ProjectedRange = y.projectedRange
}).ToList())
Return query
End Using
End Function
I'm getting that error on this part of the LINQ query (Im assuming that is that portion is highlighted in green in VS2013)
Function(x) x.Select(Function(y) New ProjectionPerformance() With {
Do I have to retrieve the actual field values and eliminate the Let statements and do the calcs in the List function of the Dictionary call?
Based on your comments, I suspect that the problem is that you try to assign null values to the double properties in ProjectionPerformance. It should work if you change your code as follows:
Dim query = (From d In ctx.projections
Where d.SymbolId <= 42 AndAlso d.Date >= lookbackDate
Join t In ctx.symbols On d.SymbolId Equals t.Id
Let actualRange = d.ActualHigh - d.ActualLow
Let projectedRange = d.HighProjection - d.LowProjection
Select New With {
d.Date,
d.SymbolId,
t.Name,
projectedRange,
actualRange}).GroupBy(Function(o) o.SymbolId).ToDictionary(Function(p) p.Key,
Function(x) x.Select(Function(y) New ProjectionPerformance() With {
.SymbolId = y.SymbolId,
.ProjectionDate = y.Date.ToString(),
.Name = y.Name,
.ActualRange = If(y.actualRange, 0.0),
.ProjectedRange = y.projectedRange
}).ToList())
In order to spot such errors before running the program, you should set OPTION STRICT to ON (either on project or file level).

grouping in LINQ query

Given a table of thousands of rows of data as shown in the sample below
Id Date SymbolId NumOccs HighProjection LowProjection ProjectionTypeId
1 2014-04-09 28 45 1.0765 1.0519 1
2 2014-04-10 5 44 60.23 58.03 1
3 2014-04-11 29 77 1.026 1.0153 1
and a Class defined as
Public Class ProjectionPerformance
Public symbolId As Integer
Public Name as String
Public Date as String
Public ActualRange as Decimal
End Class
I am trying to return the following for each symbolId;
The symbolId (from this table)
The symbol Name (from the symbols table)
The Actual Range (High Projection - Low Projection)
Can this be done in one query since i am essentially in need of a Dictionary(Of Integer, List(Of ProjectionPerformance)) where the integer is the symbolId and the List is generated from the query?
Updated:
So as to be a little clearer, Here is what I'm doing so far but contains two LINQ iterations
Public Shared Function GetRangeProjectionPerformance(Optional daysToRetrieve As Integer = 100) As Dictionary(Of Integer, List(Of ProjectionPerformance))
Dim todaysDate As Date = DateTime.Now.Date
Dim lookbackDate As Date = todaysDate.AddDays(daysToRetrieve * -1)
Dim temp As New Dictionary(Of Integer, List(Of ProjectionPerformance))
Using ctx As New ProjectionsEntities()
Dim query = (From d In ctx.projections
Where d.SymbolId <= 42 AndAlso d.Date >= lookbackDate
Join t In ctx.symbols On d.SymbolId Equals t.Id
Let actualRange = d.HighProjection - d.LowProjection
Select New With {
d.Date,
d.SymbolId,
t.Name,
actualRange}).GroupBy(Function(o) o.SymbolId).ToDictionary(Function(p) p.Key)
For Each itm In query
Dim rpp As New ProjectionPerformance
Dim rppList As New List(Of ProjectionPerformance)
If itm.Value.Count > 0 Then
For x As Integer = 0 To itm.Value.Count - 1
Dim bb As Integer = Convert.ToInt32(itm.Value(x).SymbolId)
With rpp
.SymbolId = bb
.ProjectionDate = itm.Value(x).Date.ToString()
.Name = itm.Value(x).Name
.ProjectedRange = itm.Value(x).actualRange
End With
rppList.Add(rpp)
Next
End If
temp.Add(itm.Key, rppList)
Next
End Using
Return temp
End Function
I'm going to answer in C#, but I think you'll get the gist of it anyway. Basically, you can group by SymbolId, build your object graph and then use ToDictionary using the Key to create dictionary.
var result = (From d In _projectionEntities.projections
Where d.SymbolId <= 42
group d by d.SymbolId into g
select new {
SymbolId = g.Key,
ProjectionPerformances =
g.Select(gg=>new ProjectionPerformance{
SymbolId = gg.SymbolId,
Name = gg.Symbol.Name,
rpDate = gg.Date.ToString(),
ActualRange = gg.HighProjection - gg.LowProjection
})
.ToDictionary(g=>g.SymbolId);
Try
Dim Result = (From d In _ProjectionEntities.projections
Join t In _projectionEntities.symbols On d.SymbolId Equals t.Id
Where d.SymbolId <= 42
Select New With {.SymbolID = d.SymbolID
.Date = d.Date
.Name = t.Name
.ActualRange = d.HighProjection - d.LowProjection})

Linq To SQL: left join and vb.NET

I have this SQL query:
SELECT TOP 1 r.* FROM dbo.Request r
LEFT JOIN dbo.Process p
ON r.IdReq = p.IdReq
WHERE IdProcess Is NULL
ORDER BY r.ReqDate ASC
I want write it in a vb.net procedure, using Linq To SQL syntax:
Private Function getOldestRequest() As Request
Dim dc As ProcessDataContext = new ProcessDataContext(ConfigurationManager.ConnectionStrings("...").ConnectionString);
Dim pr = From r In dc.Request
From p In dc.Process.Where(Function(v) v.IdReq = r.IdReq And v.idProcess Is Nothing)
Select New {Request = r}
Return pr
End Function
This is what I wrote, but I get error, on the Return line.
LINQ statements return IEnumerable objects, and your method is returning a single Request object. In your case looks like you only need to return the first result of the LINQ statement.
Something like:
Dim pr = (From r In dc.Request
From p In dc.Process.Where(Function(v) v.IdReq = r.IdReq And v.idProcess Is Nothing)
Select New {Request = r}).FirstOfDefault
Return pr
Change your Select to
Select r
And your return to
Return pr.OrderBy(Function(v) v.RecDate).FirstOrDefault

Convert an object System.Data.Linq.DataQuery to System.Linq.IQueryable?

How can I convert an object of type System.Data.Linq.DataQuery to System.Linq.IQueryable?
I'm working with Visual Basic/Silverlight, and the source code of my query is as follows:
Public Function Get_Cli_Pag() As IQueryable(Of V_Cliente_Pagare)
Dim Qry = From P In Me.Context.Pagares Join C In Me.Context.Codigos On C.Codigo
Equals P.Tipo_Pagare Where P.Nulo = 0 And P.Extraviado = 0 And C.Clave = 5 Select P.Rut, P.Cliente.Nombre, P.Tipo_Pagare, Tipo_Pagare_Descripcion = C.Descripcion, P.Pagare
Return Qry.AsQueryable
End Function
Does the .AsQueryable extension method work?