I'm trying to take the final solution from Phil Haack here and sort using his killer LINQ query but instead of using data context like he is, I want to query against IEnumerable(Of T) ... not having any luck.
Public Function DynamicGridData(ByVal sidx As String, ByVal sord As String, ByVal page As Integer, ByVal rows As Integer) As ActionResult
Dim list As List(Of User) = UserService.GetUserCollection()
Dim FilteredAndSortedList = list.OrderBy(sidx + " " + sord).Skip(pageIndex * pageSize).Take(pageSize)
Return JSON(jsonData)
End Function
Currently I get the error below my .OrderBy(sidx + " " + sord) line
"Data type(s) of teh type parameter(s) in extension method 'Public Function OrderBy(Of TKey)(keySelector As System.Func(Of User, TKey)) As System.Linq.IOrderedEnumerable(Of User)' defined in 'System.Linq.Enumerable' cannot be inferred from these arguments. Specifying the data type(s) explicitly might correct this error."
EDIT:
I found the issue to be that my "list" in the example above was not of type IQueryable. Simply adding .AsQueryable() did the trick!
Public Function DynamicGridData(ByVal sidx As String, ByVal sord As String, ByVal page As Integer, ByVal rows As Integer) As ActionResult
Dim list As List(Of User) = UserService.GetUserCollection()
Dim FilteredAndSortedList = list.AsQueryable().OrderBy(sidx + " " + sord).Skip(pageIndex * pageSize).Take(pageSize)
Return JSON(jsonData)
End Function
I'm not positive but I think it has to do with the fact that your passing into OrderBy a string as opposed to an Expression(TDelegate) which is what it expects.
Take a look at this article and see if it helps.
http://msdn.microsoft.com/en-us/library/bb549264.aspx
Edit:
I've taken a look at Phil's Code and at some further documentation provided by Scott Gu. You should be able to pass in a string in which to order by. That being the case my next question would be if you take out the order by does your app work? The reason for this is I'm wondering if we have another underlying error that we are missing. Like for instance you are returning JSON(jsondata) but I dont see where you are initializing jsondata. Now I dont think that is your error cause you state you are getting it on the orderby statement. However if you are actually getting the error because the object you are trying to order is empty then you have another underlying issue.
this worked for me
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
Related
Imagine this call which uses three fluent API's to make a very simple and readable function (the IQueryable Where and OrderBy, the AutoMapper Project and To, and ToDataSourceResult from Kendo).
Return Json(DataSource.TemplateItems.Where(Function(x) x.TemplateID= id) _
.OrderBy(Function(x) x.SortOrder) _
.Project() _
.To(Of TemplateIdRowViewModel) _
.ToDataSourceResult(req))
For debugging, I sometimes want to examine the current value being passed around in between calls to the fluent API. For example, I might want to know what my IQueryable looks like after Project and To finish with it but before ToDataSourceResult gets it.
I'm using the VS 2010 debugger. Right now I find myself editing the call to include temporary variable for each step so I can examine them, like this:
Dim where = DataSource.TemplateItems.Where(Function(x) x.TemplateID = id)
Dim ordered = where.OrderBy(Function(x) x.SortOrder)
Dim projected = ordered.Project().To(Of TemplateIdRowViewModel)()
Dim result = projected.ToDataSourceResult(req)
Dim jsonified = Json(result)
Return jsonified
I have this Sub which does the calculation get the information from CSV file.
Private Sub getTotalAmt(intDuration As integer, strProgrameType As String)
I've another Sub:
Private Sub getMembershipDiscount(ByRef dtDOB As Date, dblTotalAmt as Double)
which calculates the age of the customer and based on their age, gives them discount. So to do this, I've got to get the total amount from the above Sub (getTotalAmt) to this Sub procedure.
My question is, how to receive total amount from that sub procedure?
by definition, subroutines don't have output.
Instead, you want to write a function. In your case, change the code you have to something like this:
private function getTotalAmt(intDuration As integer, strProgrameType As String) as double
'do the same maths you do in the sub, and store your answer in a variable called "whatever"
getTotalAmt = whatever
end function
then to use the function:
sub IUseFunctions()
dim myDiscount as double
myDiscount = getTOtalAtm(1,"s")
end sub
In this example case, I've decided for you that the discount value is stored in a double type number. You can change that to whatever you like, at the top line of the getTotalAmt function.
Please speicify return types and convert your Sub to a Function
In that way you can always return something from your Functions,
if you specify a return type to your getTotalAmt(int Duration As Integer, StrProgrameType As String) method , That would be look like this Function getTotalAmt(int Duration As Integer, StrProgrameType As String) As double
then from another method you can call it and use retuned value of it for further calculation or whatever.
i.e
Private Sub sub1()
//You use the Sub2's value in here like
msgbox(sub2)
End Sub
Private Function sub2() As String //You can specifiy any data type you are returning, I specified String just for demnostrate
//Set the value of Sub2 in here
sub2 = "Yourvalue";
End Function
I am looking for since few hours on the Internet but I don't find if it is possible to pass to a function a collection byval ?
I put an example below and as you can see, the function ObjPtr return the same long pointer thus collTemp and myCollection are the same despite ByVal argument.
Is anyone have an idea ?
My code :
private sub function1
dim myCollection as new collection
call myFunction(mycollection)
'For example, ObjPtr(myCollection) = 123456
end sub
'in another class
private sub myFunction(ByVal collTemp as Collection)
'some code
'ObjPtr(collTemp) = 123456
end sub
Objects are not passed "by reference" or even passed at all. What you are passing are object references and these can be passed ByVal or ByRef.
If you pass one ByRef the procedure can modify what object the caller's reference actually references.
If you wish to return a new Collection instance then create one and return a reference to it.
You're passing the collection ByVal, not passing ByVal the value stored inside the collection.
Why not pass by reference, clone the values inside your method, and use the cloned values?
check here
When looking at the Collection as an object passed ByVal, the only thing actually being cloned is the reference to the collection...
I believe ByVal and ByRef don't work with Call inside the same component. Try the same but omit the Call
Please have a look at the following code, which I have run in VB6 and .NET:
Private Sub Form_Load()
Dim TestArray3() As String
TestArray3 = TestArrayFunction
End Sub
Private Function TestArrayFunction() As String()
Dim TestArray1(0 To 1) As String
Dim TestArray2() As String
TestArray1(0) = "Monday"
TestArray1(1) = "Tuesday"
TestArray2 = TestArray1
TestArray1(0) = "Wednesday"
End Function
When the program gets to the end of TestArrayFunction in VB6, the value of TestArray2(0) is "Monday", however when run in .NET, it is "Wednesday". I understand in .NET that an Array is an object and has two references pointing to it in TestArrayFunction. Why is this not the case in VB6?
This is to add to Dabblernl's response.
Long story made short, VB6 never really had a general reference type. Being built on COM, the only reference type it has (Dim ... As Object) is one for COM-based (or COM styled) classes. The Variant type was only good at boxing other types.
As to why ByRef works with arrays ...
The evolution of many dialects of BASIC, including VB6, adopted/adapted the paradigm of FORTRAN when it came to subroutines and functions; namely, parameters are passed by address (hence, ByRef is the default), and functions return their results by value. Add to this that BASIC never really had the concept of an address or a reference: VB6 (and earlier versions) would simulate addresses with 32-bit (signed) integers and otherwise would cope (in strange ways) via peculiar rules of the DECLARE SUB/FUNCTION statement and the (shoe-horned) AddressOf operator and VarPtr/StrPtr functions.
Final note: Since VB6 classes are COM-style, VB6 has the SET statement. The reason for this is that without the SET, an l-value = r-value situation is an implied LET statement. COM supports the notion of a default property (with and without parameters); LET objA = objB is interpreted as LET objA.DefaultPropOfA = objB.DefaultPropOfB. SET, on the other hand, makes objA take on the reference to the same object that objB references.
The Visual Basic of .NET is a nice and powerful language, with far fewer shortcomings and warts than VB6. However, it does have big differences from its legacy cousin. These differences have made long time VB6 users grouchy, and I suspect it has made many VB.NET users confused when they're asked to deal with VB6 code.
BTW, a VB6 coder would deal with the array within a class issue in this way:
Public Property Get DaysOfWeek(ByVal index As Integer) As String
DaysOfWeek = m_strDaysOfWeek(index)
End Property
Public Property Let DaysOfWeek(ByVal index As Integer, ByRef value As String)
m_strDaysOfWeek(index) = value
End Property
That would allow syntax of strDay = clsDateTime.DaysOfWeek(1) and clsDateTime.DaysOfWeek(2)="Tuesday" to work as desired.
I am struggling with this nearly daily. While it is perfectly possible to pass an array ByRef to a Function call, the '=' sign will make a shallow copy.
But there is more strange behaviour of arrays in VB6, Suppose you have the following DateTimeClass classmodule in VB6:
Option Explicit
Private m_strDaysOfWeek() As String
Public Property Get DaysOfWeek() As String()
DaysOfWeek = m_strDaysOfWeek()
End Property
Public Property Let DaysOfWeek(strDaysOfWeek() As String)
m_strDaysOfWeek() = strDaysOfWeek
End Property
Private Sub Class_Initialize()
ReDim m_strDaysOfWeek(7)
m_strDaysOfWeek(1) = "Monday"
End Sub
You would expect to be able to write code like:
Dim clsDateTime As New DateTimeClass
Dim strDay As String
strDay = clsDateTime.DaysOfWeek(1)
Or:
clsDateTime.DaysOfWeek(2)="Tuesday"
But you can't. You have to do it like this:
Dim clsDateTime As New DateTimeClass
Dim strDay As String
Dim strDays() As String
strDays = clsDateTime.DaysOfWeek
strDay = strDays(1)
strDays(2) = "Tuesday"
clsDateTime.DaysOfWeek = strDays
What the reasons of the VB6 team were at the time to implement it thus? I don't know...
I have abandoned the VB6 arrays and use Collections and Dictionaries nearly exclusively.
VB6 copies the array, and the last statement of your Function only changes the original copy.
Since you know .Net broke compatibility with VB I'm not sure where the confusion comes from.
(I am new to Schema validation)
Regarding the following method,
System.Xml.Schema.Extensions.Validate(
ByVal source As System.Xml.Linq.XDocument,
ByVal schemas As System.Xml.Schema.XmlSchemaSet,
ByVal validationEventHandler As System.Xml.Schema.ValidationEventHandler,
ByVal addSchemaInfo As Boolean)
I am using it as follows inside a IHttpHandler -
Try
Dim xsd As XmlReader = XmlReader.Create(context.Server.MapPath("~/App_Data/MySchema.xsd"))
Dim schemas As New XmlSchemaSet() : schemas.Add("myNameSpace", xsd) : xsd.Close()
myXDoxumentOdj.Validate(schemas, Function(s As Object, e As ValidationEventArgs) SchemaError(s, e, context), True)
Catch ex1 As Threading.ThreadAbortException
'manage schema error'
Return
Catch ex As Exception
'manage other errors'
End Try
The handler-
Function SchemaError(ByVal s As Object, ByVal e As ValidationEventArgs, ByVal c As HttpContext) As Object
If c Is Nothing Then c = HttpContext.Current
If c IsNot Nothing Then
HttpContext.Current.Response.Write(e.Message)
HttpContext.Current.Response.End()
End If
Return New Object()
End Function
This is working fine for me at present but looks very weak. I do get errors when I feed it bad XML. But i want to implement it in a more elegant way. This looks like it would break for large XML etc.
Is there some way to validate without the handler so that I get the document validated in one go and then deal with errors?
To me it looks Async such that the call to Validate() would pass and some non deterministic time later the handler would get called with the result/errors. Is that right?
Thanks and sorry for any goofy mistakes :).
I have been working with the above code for some time now and I was incorrect about it being Async. It does not move to the next statement before the whole document is validated.