|
I'm using entity framework.
I have generated the model.edmx with a wizard process.
For an entity , Myobj1 I have added a not-mapped property :
Partial Public Class Myobj1
<NotMapped> Public Property sumvalue As Decimal
End Class
Now I have this query :
Dim lst = (From t In context.MyObj1 _
where t1.id>6 Select New With { _
.Parent = t, _
.sash = t.child1.Where(Function(t2) t2.tp=2) _
.Select(Function(t3) t3.quantity), _
.DefaultIfEmpty().Sum(), _
}).ToList
I want that instead of .sash , to put the sum value into the not-mapped property .sumvalue.
Is this possible to do this in my query, and if yes , how can I do ?
Thank you !
|
|
|
|
|
Hello !
I'm using Entity framework. I have this scenario :
ParentObject - has a child collection : Child1.
On the Form I have 1 checkbox and 1 button. I have a report that display the PArentObject and the corresponding list of Child1.
the Onclick's event of the button has this code :
context.Configuration.LazyLoadingEnabled = False
Dim plist as IQueryable(Of ParentObject)
Dim chlist as IQueryable(of Child1)
plist=context.Set(Of ParentObject)
chlist=context.Set(of Child1)
plist.ToList()
chlist=chlist.Where(Function(t1) plist.Any(Function(t2) t2.id=t1.parent))
If checkbox1.checked then chlist=chlist.Where(Function(t1) t1.vl>0)
chlist.ToList()
MyReport.Datasource=plist.ToList
These are the result when I press the button :
1) With checkbox checked , Press the button ( first time ) - The report display all the Parent , each of them with only the childs that have vl1>0 ( **Correct** )
2) With checkbox unchecked , press the button (second time ) - The report display all the Parent with all the childs ( **Correct** )
3) With checkbox checked , press the button ( third time ) - The report display all the parent with all the childs ( **Not correct** )
I close the form , and re-open it
1) With checkbox unchecked , press the button (First time ) - The report display all the Parent with all the childs ( **Correct** )
2) With checkbox checked , press the button ( Second time ) - The report display all the parent with all the childs ( **Not correct** )
Why I get not correct results when repeating the queries like in the examples above ? What should I do in these cases ?
Thank you !
|
|
|
|
|
I have a windows form with code in VB 2010, developed with VS 2010. I upgraded it from an earlier VB version. There is a message box in a procedure that runs with a button click. But this message box shows on form load before the form is visible. If I remove the message box, the form loads as expected. What can be wrong?
Bobby
|
|
|
|
|
BobbyStrain wrote: What can be wrong? Anything at all. But you need to show the code that has the problem if we are to help you.
|
|
|
|
|
Here is the form load and button click code. Only relevant code shown on button click.
Private Sub HoSepForm_Load(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles MyBase.Load
'Plug in default values when the form loads
txtVaporViscosity.Text = CStr(0.01)
txtLiquidViscosity.Text = 0.5
ddlVesselConfig.SelectedIndex = 0
ddlVesselTypes.SelectedIndex = 0
spnLiquidSurge.Value = 10
txtDesignPressure.Text = CStr(250)
cmdKOType.Text = "Process Separator"
cmdConfig.Text = "1 Inlet & 1 Outlet"
cmdMaterial.Text = "CS"
cmdDiameterIncrease.Visible = False
cmdDiameterDecrease.Visible = False
txtVaporFlow.Text = 300000
txtLiquidFlow.Text = 100000
txtVaporDensity.Text = 0.5
txtLiquidDensity.Text = 50
txtTemperature.Text = 110
txtOperatingPressure.Text = 200
txtWaterFlow.Text = 10000
ckDemister.Checked = False
lstDropSize.SelectedIndex = 0
ddlDemister_h.SelectedIndex = 0
ddlDemister_h.Visible = False
ddlDemisterDim.Visible = False
Label23.Visible = False
End Sub
Sub cmdSize_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles cmdSize.Click
(dim and some code)
'Capture all the input parameters & values
SepType = cmdKOType.Text
Material = cmdMaterial.Text
DesignPressure = Val(txtDesignPressure.Text)
VaporMassFlow = Val(txtVaporFlow.Text)
LiquidMassFlow = Val(txtLiquidFlow.Text)
VaporDensity = Val(txtVaporDensity.Text)
LiquidDensity = Val(txtLiquidDensity.Text)
VaporVisc = Val(txtVaporViscosity.Text)
'LiquidVis = Val(txtLiquidViscosity.Text)
DropSize = Val(lstDropSize.Text)
HoldTime = Val(lblLiquidSurge.Text)
OpTemperature = Val(txtTemperature.Text)
WaterRate = Val(txtWaterFlow.Text)
'Validate that the input is complete
If VaporDensity * LiquidDensity * VaporVisc * DropSize > 0 Then
'Input complete, so calculate drop settling velocity
DropSpeed = Calculate_Drop_V(DropSize, VaporDensity, LiquidDensity, VaporVisc)
'Then stick it in the output label on the form
lblDropSpeed.Text = CStr(System.Math.Round(DropSpeed, 2))
'Calculate vapor/liquid volumetric flow & holdup volume
CFSV = VaporMassFlow / VaporDensity / 3600
CFSL = LiquidMassFlow / LiquidDensity / 3600
'LVol = CFSL * 60 * HoldTime
waterdensity = Water_Density(OpTemperature)
WaterVol = WaterRate / waterdensity / 60
LVol = ((CFSL * 60) + WaterVol) * HoldTime
watervisc = Water_Vis(OpTemperature)
totalliquid = CFSL * 60 + WaterVol
totalliquiddensity = (LiquidMassFlow + WaterRate) / totalliquid / 60
lblWaterDensity.Text = CStr(Math.Round(waterdensity, 2))
lblWaterViscosity.Text = CStr(Math.Round(watervisc, 2))
'If the input is incomplete, then exit the form, alerting the user.
Else
-> this is msgbox that shows before form is visible MsgBox("Input not complete")
Exit Sub
End If
(more code)
|
|
|
|
|
...and? That's the expected behavior. Form_Load fires before the form is rendered on screen. Are you perhaps looking for the Form_Shown event?
|
|
|
|
|
Dave,
Looking at the code you will see that the message box is not in the form load event, but in a button click event. The button is on the form. I have lots of projects like this one and have never before encountered this behavior.
Bobby
|
|
|
|
|
Your code doesn't make any sense. Is the button Click event and the Load event handles in the same form?
If so, what are you doing to call the Click handler without the form being visible?
Unless you've done something very f'ed up in your code it is not possible for THAT messagebox line to be executed when you say it is.
|
|
|
|
|
Dave,
Your question is exactly the one I am looking to answer. There is no call to the button click event. So, I wonder where the call might be coming from. When I remove the message box from the button click event everything works as it should and the form loads.
Bobby
|
|
|
|
|
We can't see your code so it's up to you to find the problem.
I'd start by putting a breakpoint in the top of the button Click event handler and running the code. Look at the Call Stack to see where the call came from.
|
|
|
|
|
Dave,
The call is from a radio button, but I have no idea where the call originates. It must be buried somewhere within the VS generated code. So I will give up and simply remove the message box. Thanks for your advice.
Bobby
|
|
|
|
|
Yeah I seriously doubt it's in the designer generated code. It won't reference anything in your event handlers, ever.
This is a sign you've got something really messed up in your code and the stack trace is your best bet for finding it. I'd take a careful look at every method listed in the stack trace.
|
|
|
|
|
BobbyStrain wrote: The call is from a radio button Whereabouts on the form is this button, and does it get initialised somewhere? You should go back to the designer and check all the properties and events of the button, it is obviously firing for some reason. And, as Dave K. says, breakpoints and stack traces should find the issue fairly quickly.
|
|
|
|
|
Richard,
I have replaced the radio buttons with checkboxes. The checkboxes are not linked, but they are located within a group box. I modified things such that the checkbox is disabled and unchecked initially. It is activated and checked at the end of the form load code. I don't get the message anymore because the form load fills in all the input data. The checkbox checked change event is still firing on form load which fires the calculation, too. I don't have a clue as to how to run a stack trace, but I guess I will need to learn. We have come a long way since I started using Microsoft basic in 1982 with an 8-bid Z-80 4 mh processor. I have lots of small applications using VB.net and this is the first time I have encountered such mysterious behavior. It probably is related to upgrading with VS 2010. Thanks for your help. And you, too, Dave.
Bobby
|
|
|
|
|
BobbyStrain wrote: I don't have a clue as to how to run a stack trace, but I guess I will need to learn. Set a breakpoint in the source code window (click in the margin by the first line of code) of Visual Studio and press F5 to run the program in the debugger. When it stops at the debug point you can single step through the code, line by line, and inspect and change the variables, so you can see exactly what is happening. The debugger is probably the most useful tool at your disposal, so you should really get familiar with it. MSDN has some help information about it at https://msdn.microsoft.com/en-us/library/ms172744.aspx[^].
|
|
|
|
|
After further study, the checkbox change event is triggered during form load. So its handler is executed. I didn't realize that this is normal behavior. I already have a hidden label on the form that is used for another purpose, so I set the text during form load before enabling the checkbox, then skipped the message box display in the handler based on the value. I don't understand enough about senders and sender arguments, but this is probably the professional approach. So I learned a few new things. Thank you both.
Bobby
|
|
|
|
|
I'm trying to run the following query :
Dim lst = (From t In context.MyObj1 where t1.id>6 Select New With { _
.Parent = t, _
.sash = t.child1.AsQueryable.Where(Function(t2) t2.tp=2).Sum(Function(t3) t3.quantity), _
.vlh = t.child1.AsQueryable.Where(Function(t3) t3.tp=2).Sum(Function(t3) t3.value) _
}).ToList
( in this query .quantity and .value have Decimal type.)
but I'm getting this error on runtime :
An unhandled exception of type 'System.InvalidOperationException' occurred in EntityFramework.dll
Additional information: The cast to value type 'System.Decimal' failed because the materialized value is null.
Either the result type's genericparameter or the query must use a nullable type.
It's sure that the collection child1 has items that have .tp=2.
What's wrong ? Thank you !
|
|
|
|
|
It's pretty simple really. It's telling you that, somewhere in your data, you have a null value in the database where this code is expecting a value. It can't convert a null to a Decimal type.
|
|
|
|
|
If I run the query like this :
Dim lst = (From t In context.MyObj1 where t1.id>6 Select New With { _
.Parent = t, _
.sash = t.child1.AsQueryable.Where(Function(t2) t2.tp=2).Select(Function(t3) t3.quantity), _
.vlh = t.child1.AsQueryable.Where(Function(t3) t3.tp=2).Select(Function(t3) t3.value) _
}).ToList
Everything is ok. And it's sure that all the value on database are not null.
So the problem is the function Sum.
|
|
|
|
|
I already told you how to get the query string from the IQueryable object.
Get and execute it in SQL Server Manager. This is an INVALUABLE technique for diagnosing problems in your LINQ query.
I think you'll find the the Sum operation isn't done by LINQ, but by the database engine. You'll also find that the SQL that is generated isn't what you think it is.
modified 16-Feb-15 8:58am.
|
|
|
|
|
It's strange because if I replace the Sum function with Count function , everything works ok , and count values are not Null.
Dim lst = (From t In context.MyObj1 where t1.id>6 Select New With { _
.Parent = t, _
.sash = t.child1.AsQueryable.Where(Function(t2) t2.tp=2).Count(Function(t3) t3.quantity), _
.vlh = t.child1.AsQueryable.Where(Function(t3) t3.tp=2).Count(Function(t3) t3.value) _
}).ToList
|
|
|
|
|
If you try to Count a null collection, it works because there's nothing to Count.
If you try to Sum a null collection, 0 + null isn't defined, so it throws.
|
|
|
|
|
That's the the great thing about LINQ: you can write the most complex operations in a single statement so when it fails you have no idea where the problem is.
|
|
|
|
|
These are the tables :
MyObj1:
Id name
2 name1
7 name7
8 name8
Child1:
ID ParentID TP Quantity Value
1 2 2 7 9
2 7 2 20 10
3 7 2 8 11
( ParentID is the forign key for child1 related to ID field on MyObj )
So the problem is on my query structure or in the tables ?
|
|
|
|
|
Based on that data, you don't have any Child1 rows for the MyObj1 row with ID 8. Since that row is included in your outer query (where t1.id > 6 ), you're trying to take the Sum of an empty sequence.
It seems that the EF query is returning NULL from the database, and then trying to convert that to a Decimal value. This issue is discussed on Matteo Tontini's Blog[^], albeit for C#.
Try casting the properties to Decimal? / Nullable(Of Decimal) before summing them.
Nullable Value Types (Visual Basic) - MSDN[^]
Dim lst = (From t In context.MyObj1 where t1.id>6 Select New With { _
.Parent = t, _
.sash = t.child1.AsQueryable.Where(Function(t2) t2.tp = 2).Sum(Function(t3) DirectCast(t3.quantity, Decimal?)), _
.vlh = t.child1.AsQueryable.Where(Function(t3) t3.tp = 2).Sum(Function(t3) DirectCast(t3.value, Decimal?)) _
}).ToList
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|