Join In queryover in NHibernate - sql

I am using NHibernate. I want to use join on queryover, try following code but this gives error,
session.QueryOver(Of Messages)()
.Where(Function(x) x.UserID_Messages.Username.Contains(msgfrom))
.And(Function(x) x.Message.Contains(msg))
.And(Function(x) x.MsgDate >= startdate)
.List
But this error = Unrecognised method call: System.String:Boolean Contains(System.String)
And if i try this query
session.QueryOver(Of Messages)
.JoinQueryOver(Of Users)(Function(x) x.UserID_Messages)
.WhereRestrictionOn(Function(x) x.Username).IsLike("%" & tosearch & "$")
.List(Of Messages)()
This result empty, even record is there in database. Please guide what am I doing wrong, or what is correct way to achieve this. Thanks

The .Contains method, is a .NET method, which is not translated into SQL statement when using QueryOver syntax. The second approach, with QueryOver native method IsLike is what we need. To be sure, that we will end up with a SQL like this:
username LIKE '%the searched value%'
we should use the built in MatchMode
.WhereRestrictionOn(Function(x) x.Username).IsLike(tosearch, MatchMode.Anywhere)
See the MatchMode class definition

Related

LINQ retrieving a record based on date

I am trying to learn a bit about ling. in the code below, I'm trying to retrieve records that have an activeuntil date which after the current date.
Dim context As DynamicsCRMEntities = New DynamicsCRMEntities()
Dim CustomerNoticeQuery = From NewsArticles In context.BusinessUnitNewsArticles Where NewsArticles.NewsArticle Like "customer" Select NewsArticles.ArticleTitle, NewsArticles.NewsArticle, NewsArticles.ActiveUntil
For Each result In CustomerNoticeQuery
If Date.Now.Date >= result.ActiveUntil Then
CustomerNotice.Text = result.NewsArticle.ToString
End If
Next
I keep running into this error but cannot get my head around it
System.NotSupportedException: 'LINQ to Entities does not recognize the method 'Boolean LikeString(System.String, System.String, Microsoft.VisualBasic.CompareMethod)' method, and this method cannot be translated into a store expression.'
The Like operator you are using there is VB-specific and, as the error message says, is not supported by EF. You need to use standard .NET functionality that the LINQ to Entities provider understands. If you want to do a partial match on Strings, that means using String.Contains:
Dim CustomerNoticeQuery = From NewsArticles In context.BusinessUnitNewsArticles
Where NewsArticles.NewsArticle.Contains("customer")
Select NewsArticles.ArticleTitle, NewsArticles.NewsArticle, NewsArticles.ActiveUntil
You really ought to break your LINQ queries over multiple lines like that too, for the sake of readability.
Note that that addresses your actual issue, which has nothing to do with dates, so the date part to the question was completely irrelevant. That said, why would you do a query with a Where clause and then use a loop to filter the results of that query? Why would you not include the additional filter in the Where clause? I'd also consider using a better subject variable name in the query:
Dim today = Date.Today
Dim CustomerNoticeQuery = From article In context.BusinessUnitNewsArticles
Where article.NewsArticle.Contains("customer")
And article.ActiveUntil < today
Select article.ArticleTitle, article.NewsArticle, article.ActiveUntil

Execute inline sql to update a table using nHibernate

Sorry if this has been asked before, I did a search but couldn't find anything.
Is it possible to execute inline sql in nHibernate? I have something like this which I would like to run against the dB:
_session.CreateSQLQuery(
#"update things
set defaultThing = 0 where parentId = :parentId AND thingId <> :thingId")
.SetInt32("parentId ", parent.Id)
.SetInt32("thingId", thing.Id)
;
I suppose I could loop through a bunch of 'things' and set the defaultThing setting to false then call _session.Update(thing), but if I can do it how I outlined above, that would be great.
Yes, just use ExecuteUpdate() on that query. It's the equivalent of IDbCommand.ExecuteNonQuery().
As kay mentioned, you can use HQL too. Check 12.3. DML-style operations

nHibernate 3.0 queries

Working through the summer of nHibernate tutorials have gotten to the section on queries. Seems there have been changes since that series was made. So I went to the online docs for nHB 3.0 but code such as:
IList cats = session.CreateCriteria(typeof(Cat))
.Add(Expression.Like("Name", "Fritz%"))
.Add(Expression.Between("Weight", minWeight, maxWeight))
.List();
Generates the error "The name 'Expression' does not exist in the current context"
Code like:
return session.CreateCriteria(typeof(DataTransfer.Customer))
.Add(new NHibernate.Criterion.LikeExpression("Firstname", firstname))
.Add(new NHibernate.Criterion.LikeExpression("Lastname", lastname))
.List<Customer>();
Works but it seems that it is missing a number of query methods like GtExpression.
Are the online docs up to date, and if so, why can't I use Expression...
If the online docs aren't up to date then where do I get a description of the Criterion interface?
Thanks
You forgot to add using NHibernate.Criterion;.
Anyway, the Expression class is deprecated. Use Restrictions instead.
Weird thing. I still use Expression.* static methods and these are still work. Are you sure you use the latest version of NH3.0? I use Alpha 2 version.
If you need to make it work urgently, let's try the QueryOver<> feature:
return session.QueryOver<DataTransfer.Customer>()
.WhereRestrictionOn(u => u.Name).IsLike("Fritz%")
.AndRestrictionOn(u => u.Weight).IsBetween(minWeight).And(maxWeight)
.List();
It works well for simple queries

NH QueryOver FetchMany Exception

I am trying to query a parent User and then their UserRoleMappings. I have something similar to the below statement:
Dim userObj As User = session.Queryable(Of User)().Where(Function(x) x.username.Equals("someone")).FetchMany(Function(y) y.UserRoleMappings).SingleOrDefault()
When I try to run this statement I get the following exception:
A fetch request must be a simple member access expression; 'Convert(y.UserRoleMappings)' is a UnaryExpression instead.
Parameter name: relatedObjectSelector
I can confirm that I got this to work in a C# Test Case, but unfortunately I need it to work in VB. Can anyone assist?

Method 'Boolean Contains(System.String)' has no supported translation to SQL

"Method 'Boolean Contains(System.String)' has no supported translation to SQL."
query is IsQueryable but this stopped working:
foreach (string s in collection1)
{
if (s.Length > 0)
{
query = query.Where(m => m.collection2.Contains(s));
}
}
UPDATE: it works when i make query "ienumerable" instead of iqueryable. What would be the way to get same result using linq instead of iterating through loop?
Try this:
query = query.Where(m => m.collection2.ToList().Contains(s));
^^^^^^^^
Take a look at this answer from stackoverflow.
It looks like the resulting query would need access to something that the database
has no way of reaching, because the info is in memory.
Since m.collection2 is in the database, don't use Contains. Use Any
m.collection2.Any(x => x == s)
It looks like the error you are seeing is coming from the collection collection 2. Have you tried wrappering the m.collection2 in another function which returns true or false? Is this LINQ syntax?