late binding in linq - vb.net

I have a simple LINQ query that is going against a collection.
Dim oList = From w In Os
Order By w.ClassTitle Descending
Select w
What I'd like to be able to do though is pass into this whether it's descending or ascending. I'm not sure how to do that.
Also, if I were to have a where clause in here.. say
where w.ClassTitle = "Test"
How can I make the "Test so that I can pass it into the LINQ query.
Thanks
shannon

I dont think you can pass that "into" this query, however you could do the regular query
var oList = from w in Os
select w
Then when the user takes some action you could simply do an order by after that fact.
oList.OrderBy(o => o.ClassTitle)
or
oList.OrderByDescending(o => o.ClassTitle)
UPDATE:
As far as the late binding, what you could do is write a method that would execute the Where clause. Perhaps using an extension method might work. I'm more familiar with C# so my syntax might be a bit off
public static IEnumerable<Os> ExecuteWhere (this Table<Os> table, Expression<Func<Os, bool>> predicate)
{
return table.AsQueryable<Os>().Where(predicate);
}
Then to call it like so:
oList.ExecuteWhere(a => a.ClassTitle == "Test")

Use delegation syntax. For example;
Dim oList = Os.Where(....).OrderBy(...)...

Related

Linq to SQL Dynamic Where Clause

I have a simple query:
dim res = (From x In db.INVENTORies
Where x.INVENTORY_ACTIVATION_DATE IsNot Nothing).count
I need to run this for 14 different date fields, so how do I run this where INVENTORY_ACTIVATION_DATE can be a variable/dynamic?
something like:
function GetCount(aField as string) as integer
return (From x In db.INVENTORies
Where x.**<Use aField here>** IsNot Nothing).count
end function
Thanks in advance.
Steve
I've tried Dynamic Linq and PredicateBuilder, but there are no good examples for my scenario.
C# Eval Expression
Disclaimer: I'm the owner of the project C# Eval Expression
The library is not free, but you can do pretty much any dynamic LINQ using the same syntax as C#.
So it can be used in your VB.NET application, but you will need to use C# syntax for the dynamic part
return context.Customers.WhereDynamic("x => x.AnyField != null && x.AnyField2 != null").count
As you can see, you simply need to create the string to execute dynamically.
LINQ Dynamic
https://www.nuget.org/packages/System.Linq.Dynamic.Core/
The same can be achieved with LINQ Dynamic. You can find some where example here
You don't have to use the PredicateBuilder but simply create the string dynamically.
Through much trail and error, I finally got this working. I ended up using System.Linq.Dynamic.Core.

How to write Subset ⊆ in an operation

I want to perform logic operation to check if a string or a set of numbers is contained in a variable. In the same manner simply write:
a + b
a * b
a = b
Is there a way to write something like:
a ⊆ b
I expect te retrieve a boolean result out of it, stating true or false to determine if it is contained in the other variable. I am writing a comparison tool and would like to simplify it to use a math or logic operator instead of a method like InStr().
You can use LINQ for this:
Dim bContainsAllA As Boolean = Not a.Except(b).Any()
You can't create new operators... Your options is to use an existing operator, create a method or do an extension method.
I wouldn't recommend using InStr since this is old VB. There are good methods in the String class. Or use LINQ.

How to run a function using a nhibernate criteria?

We have a search routine that uses criteria to build SQL query (because its restrictions added dynamically).
In a particular case (a very complicated case) we need to search over a table-valued function.(our model object is mapped to the function).
The result would be something like this :
SELECT count(*) FROM dbo.GetSubStaffsLetterInstances(#staffId) WHERE LetterNumber="1234";
The problem is I don't know how to pass #staffId to my criteria(I tried adding an Eq restrictions without success since restrictions are working on properties)
I know I can add a parameter to an IQuery but I don't know how I can do it using an ICriteria object.
If I understand your question completely, you can resort back to standard SQL:-
var sql = "SELECT count(*) FROM dbo.GetSubStaffsLetterInstances(:staffId)
WHERE LetterNumber=:letterNum";
var count = session.CreateSqlQuery(sql)
.setInt32("staffId", 12345)
.setString("letternum", "A1")
.UniqueResult<int>();
or try .UniqueResult<long>(); as I can't remember which one HQL returns

Why doesn't a separately instantiated Func<T,bool> predicate not translate into SQL with Entity Framework?

I have an EF Code First Db context that I'm using to query the database. I noticed some performance issues when passing in queries as Func<Product, bool>s from my Aggregate Repository and on investigating further it turned out that the queries were not being translated into SQL Queries.
After a little more digging I discovered the following.
var results = _context.Products
.Where(p => p.ProductCode.Contains("AAA"))
.Where(p => p.CategoryId == 1)
.ToList();
This works exactly as expected. It generates some parametrized SQL with a Where Clause.
==================================================================
var results2 = _context.Products
.Where(p => p.ProductCode.Contains("AAA") && p.CategoryId == 1)
.ToList();
This also works as expected. It generates the same sql as above
==================================================================
Func<Product, bool> pred = (p => p.ProductCode.Contains("AAA") && p.CategoryId == 1);
var results3 = _context.Products.Where(pred).ToList();
This is broken. It doesn't generate the where clause in the SQL, it returns everything and then filters it in code.
Because in order to translate into SQL, it has to be an Expression<...>, not a Func<...>.
This is done automatically for you by the compiler, and since the overloads on the Linq-to-SQL classes takes expressions, not delegates, the compiler will automagically translate your code (which looks like a lambda or an anonymous method) into an expression object and pass that.
However, if you take care of building the function yourself, the compiler cannot do this, and Linq-to-SQL does not take anonymous methods, it only takes expressions.
What you can do is to execute the parts of your query that you can, and then filter the results through your function, but I would look into just changing the type of your value into an expression instead.
No sooner than I posted this ReSharper helped answer my question by showing me the overload method signature for the Where() extension method.
It takes both Func<T, bool> and Expression<Func<T, bool>>. If your declaring your predicates externally, you must use the Expression variation as the former is not translated into sql.
Here's why the query reads the whole table.
When a Func is used instead of an Expression, the compiler chooses methods on System.Linq.Enumerable - instead of System.Linq.Queryable. The Enumerable methods iterate the source collection (sometimes lazily) while the Queryable methods build up the expression tree.
Since the call to Where isn't part of the expression tree, the sql generator doesn't see it during the query translation.

LINQ - Select a *TYPED* item in a collection

Can I use LINQ to return an item in a collection that is the same TYPE as the items in the collection? I am a LINQ Noob trying to avoid looping.
Dim mostRecentlyCreatedQuestionnaire As ParentQuestionnaireItem =
CType((From P In questionnaireCollection Order By P.Metadata.CreateDate Descending).Take(1), ParentQuestionnaireItem)
I get an "unable to CAST" error when I include the CTYPE function. I kind of expected that error, but I imagine that if I coul dnot do this, LINQ's usefulness would be diminished and therefore assume that there must be a way...
Just do this:
Dim mostRecentlyCreatedQuestionnaire As ParentQuestionnaireItem =
(From P In questionnaireCollection Order By P.Metadata.CreateDate Descending).FirstOrDefault()
The problem with your approach is, that Take returns an enumerable, even if you just take 1.
My answer assumes that questionnaireCollection is strong typed.
The reason that Take(1) doesn't work is that Take(1) returns a IEnunmerable(Of TSource) or IQueryable(Of TSource) depending on the query, why First return an Object of Type TSource
Dim mostRecentlyCreatedQuestionnaire As ParentQuestionnaireItem =
DirectCast((From P In questionnaireCollection Order By P.Metadata.CreateDate Descending).First, ParentQuestionnaireItem)