I am looking for sample linq code snippet which uses System.Linq.Dynamic against a datatable.
Dim entities = (From ent In dt.AsEnumerable().Where(String.Format("IsUSFederal == {0}", "true")) _
Select Description = ent("Description"), Acronym = ent("Acronym")).ToList
I am getting an error "there is no accessible Where can be called with these arguments". I have included the DynamicLinq.vb file and the application compiles fine (aside from this error). I have included Imports System.Linq.Dynamic but it doesn't appear to be working.
Any ideas?
thx
The Enumerable.Where takes a Func(Of TSource, Boolean) as argument and your passing a String.
(update)
Didn't catch the Dynamic library part ... sorry. I think you need to do this:
dt.AsQueryable()
Because the extension methods on the library are defined as:
<Extension()> _
Public Function Where(ByVal source As IQueryable, ByVal predicate As String,
ByVal ParamArray values() As Object) As IQueryable
Related
This is a cousin of the question "Can CodeDom create optional arguments when generating a c# method?"
And I tried the answer given there.
Still, when I attempt to compile, I get the following error:
error BC30455: Argument not specified for parameter 'optionalParam' of 'Public Function Bar(optionalParam As Integer) As Integer
I've distilled this down to the Visual Basic Compiler not supporting either OptionalAttribute, DefaultParameterValueAttribute, or both.
Here's the distilled code I'm compiling:
Imports System.Runtime.InteropServices
Namespace SSI.RuntimeGenerated.FunctionsNamespace
Public Class Functions
Public Function Foo() As Integer
return Bar()
End Function
Public Function Bar( _
<[Optional], DefaultParameterValue(1)> _
ByVal optionalParam As Integer) _
As Integer
return optionalParam
End Function
End Class
End Namespace
Compiling this with the following command:
"C:\Windows\Microsoft.NET\Framework\v4.0.30319\vbc.exe" /t:library /out:foobar.dll foobar.vb /langversion:11
Produces the following output:
Microsoft (R) Visual Basic Compiler version 11.0.50709.17929
Copyright (c) Microsoft Corporation All rights reserved.
C:\<snip>\foobar.vb : error BC30455: Argument not specified for parameter
'optionalParam' of 'Public Function Bar(optionalParam As Integer) As Integer'.
return Bar()
~~~~~
If I change the method signature manually to be
Public Function Bar(Optional ByVal optionalParam As Integer) As Integer
then it compiles just fine.
So my questions are:
How to create optional arguments in Visual Basic generated through CodeDom?
Does vbc even support use of OptionalAttribute and/or DefaultParameterValueAttribute?
If vbc doesn't support those attributes, is there any possible way to create Optional arguments without resorting to using a CodeSnippetStatement?
If there's no other way, then is it possible to salvage other work I've done with CodeDom so I don't end up having to pretty much generate my methods by hand? Do I have to pretty much build the rest by hand inside a CodeSnippetTypeMember? Would even that work?
The OptionalAttribute is not supported in VB.NET. I cannot find any official documentation that specifically says so, but if you try to use it in a VB.NET project, it will have no effect. To create an optional parameter in VB.NET, you must use the Optional keyword, for instace:
Public Class Functions
Public Function Foo() As Integer
Return Bar()
End Function
Public Function Bar(Optional ByVal optionalParam As Integer = 1) As Integer
Return optionalParam
End Function
End Class
Is there a Visual Basic.NET method that can convert method parameters into an array?
For instance instead of:
Function functionName(param1 as object, param2 as object) as object
ArrayName = {param1, param2}
you could do something like:
Function functionName(param1 as object, param2 as object) as object
ArrayName = MethodThatGetsAllFunctionParams
Just curious really.
There is no way of doing that. The language itself doesn’t allow that. You can use reflection to get the currently executing method of the StackFrame of the execution. But even then it’s still impossible to retrieve the parameter values.
The only solution is to “patch” the applications by introducing point cuts into the method call. The linked answer mentions a possibility for that.
Take a look at ParamArrays. I think this solves what you're asking for?
http://msdn.microsoft.com/en-us/library/538f81ec%28v=VS.100%29.aspx
EDIT:
You could initialise a custom collection using your current function signature
Public Class CustomCollection(Of T)
Inherits System.Collections.Generic.List(Of T)
Sub New(param1 As T, param2 As T)
MyBase.New()
MyBase.Add(param1)
MyBase.Add(param2)
End Sub
End Class
and then call the function using
Dim result = functionName(New CustomCollection(Of Object)(param1, param2))
The Function signature would be changed to:
Public Function functionName(ByVal args As CustomCollection(Of Object)) As String
I'm currently working in .NET 2.0 Visual Basic. The current project is an Active Directory Wrapper class library within which I have a Searcher(Of T) generic class that I wish to use to search the underlying directory for objects.
In this Searcher(Of T) class I have the following methods:
Private Function GetResults() As CustomSet(Of T)
Public Function ToList() As CustomSet(Of T)
Public Function Find(ByVal ParamArray filter() As Object) As CustomSet(Of T)
// And some other functions here...
The one that interests me the most is the Find() method to which I can pass property and values and would like to parse my LDAP query from this filter() ParamArray parameter. Actually, all I can figure out is this:
Public Sub SomeSub()
Dim groupSearcher As Searcher(Of Group) = New Searcher(Of Group)()
Dim groupsSet as CustomSet(Of Group) = groupSearcher.Find("Name=someName", "Description=someDescription")
// Working with the result here...
End Sub
But what I want to be able to offer to my users is this:
Public Sub SomeSub()
Dim groupSearcher As Searcher(Of Group) = New Searcher(Of Group)()
Dim groupsSet As CustomSet(Of Groupe) = groupSearcher.Find(Name = "someName", Guid = someGuid, Description = "someDescription")
// And work with the result here...
End Sub
In short, I want to offer some kind of Expression feature to my users, unless it is too much work, as this project is not the most important one and I don't have like 2 years to develop it. I think that the better thing I should do is to write something like CustomExpression that could be passed in parameters to some functions or subs.
Thanks for any suggestions that might bring me to my goal!
Interesting question. This is a language dependent feature, so I don't see this happening without some clever trickery of the IDE/compiler.
You could however have optional overloads on your Find method (vb.net is good for this), then make the search string manually to obtain the result.
Finally you could make use of lambda functions, but only in .net 3.5 and above. Even still, it would require your searcher to expose a preliminary set of data so you can recover the expression tree and build up the find string.
UPDATE
I've just been playing around with Reflection to see if I can retrieve the parameters passed, and build up a string dynamically depending on if they exist. This doesn't appear to be possible, due to the fact that compiled code doesn't reference the names.
This code just used was:
'-- Get all the "parameters"
Dim m As MethodInfo = GetType(Finder).GetMethod("Find")
Dim params() As ParameterInfo = m.GetParameters()
'-- We now have a reference to the parameter names, like Name and Description
Hmm. http://channel9.msdn.com/forums/TechOff/259443-Using-SystemReflection-to-obtain-parameter-values-dynamically/
Annoyingly it's not (easily) possible to recover the values sent, so we'll have to stick with building up the string in a non-dynamic fashion.
A simple optional method would look like:
Public Sub Find( _
Optional ByVal Name As String = "", _
Optional ByVal Description As String = "")
Dim query As String = String.Empty
If Not String.IsNullOrEmpty(Name) Then
query &= "Name=" & Name
'-- ..... more go here with your string seperater.
End If
End Sub
I am trying to use the "Except" method on a LINQ result set using a custom implementation if IEqualityComparer to exclude certain results based on the value of a single field from the result set.
So, in simplified form I have...
'' Get collection of published sites...
Dim List1 = (From i In db.Sites _
Where (i.StatusID = published) _
Select i.SiteID, _
i.SiteName)
'' Find those with a pending site, but exclue all those whose SiteID is in List1...
Dim insComparer = New insCompare
Dim List2 = (From i In db.Sites _
Where (i.StatusID = pending) _
Select i.SiteID, _
i.SiteName).Except(List1, insComparer)
My Comparer is as follows...
Public Class insCompare
Implements System.Collections.Generic.IEqualityComparer(Of Object)
Public Function Equals1(ByVal x As Object, ByVal y As Object) As Boolean Implements System.Collections.Generic.IEqualityComparer(Of Object).Equals
Return IIf(x.SiteID = y.SiteID, True, False)
End Function
Public Function GetHashCode1(ByVal x As Object) As Integer Implements System.Collections.Generic.IEqualityComparer(Of Object).GetHashCode
Return x.SiteID.ToString.ToLower.GetHashCode()
End Function
End Class
I get an invalid cast exception on the ".Except" line with the message "Unable to cast object of type '...insCompare' to type 'System.Collections.Generic.IEqualityComparer'"
Can anyone cast light on why this might be please.
Your problem here is that you implement IEqualityComparer(Of Object), but your lists are List(Of AT) where AT is an anonymous type, so you can't implement IEqualityComparer(Of AT).
I think your choices are:
Declare a class/struct to hold the SideID/SiteName, and select into an instance of that class, then implement IEqualityComparer(Of NewClass).
Use late-bound calls (ie. option explicit off, like it appears you are doing now), and put a .Cast(Of Object)() call on both lists before calling Except.
Use the following code.
from t in db.Sites
where
!
(from t0 in db.Sites2
select new {
t0.SomeID
}).Contains(new { t.SomeID })
select t
this is based in not in condition. I think this will help you. U are doing some complex thing.
It looks like it's asking that your comparer implement the non-generic interface IEqualityComparer, whereas yours implements IEqualityComparer (Of Object), which is a different interface.
It looks like you are using a database as the back end. You can't provide a custom comparer for this, as it can't be mapped to TSQL.
Have you tried Contains? i.e. where !List1.Contains(i.SiteID)?
I'm still learing VB.NET and usually I just google my questions, but this time I really don't know what to look for so I'll try here.
Trying to write a function that takes the cache key as a parameter and returns the cached object. No problems there, but I can't figure out how to pass the type into the function to use with TryCast, so that I don't have to do that with the returned result.
Here is my function so far, the ??? is to be replaced with the type that is passed into the function somehow.
Public Function GetCache(ByVal tag As String) As Object
Dim obj As Object = Nothing
Dim curCache As Object = TryCast(System.Web.HttpContext.Current.Cache(tag), ???)
If Not IsNothing(curCache) Then
Return curCache
Else
Return Nothing
End If
End Function
Am I doing this completely wrong or am I just missing something?
Use a generic:
Public Function GetCache(Of T)(ByVal tag As String) As T
Return CType(System.Web.HttpContext.Current.Cache(tag), T)
End Function
update:
Edited to use CType, because trycast only works with reference types. However, this could throw an exception if the cast fails. You can either handle the exception, check the type before making the cast, or limit your code to reference types like this:
Public Function GetCache(Of T As Class)(ByVal tag As String) As T
Return TryCast(System.Web.HttpContext.Current.Cache(tag), T)
End Function