Call procedure or function as part of Hibernate query - sql

I need to return records filtered and sorted by complex logic.
I am planing to make sorting and filtering at the database side (function or stored procedure).
Is it possible to call procedure or function at the QueryOver or Criteria syntax in order to make filtering of the query?
Something like code shown below, where CallProcedure - calling my procedure/function
var articles = Session.QueryOver<ArticleData>()
.Where(x => x.CompanyId == 1)
.CallProcedure???
.Skip(startIndex)
.Take(number).List();
Thanks for help.

First, you would need to register your function with NHibernate, by creating a custom dialect:
public class MyDialect : MsSqlServer2008Dialect
{
public MyDialect()
{
RegisterFunction("myfunction", new SQLFunctionTemplate(...));
}
}
After that, you can use the function within your query:
var articles = Session.QueryOver<ArticleData>()
.Where(x => x.CompanyId == 1)
.Where(Projections.SqlFunction("myfunction", ...))
.Skip(startIndex)
.Take(number).List();
Something along those lines. Not sure if you'll be able to do both filter and sort with it though. Maybe a database view will be more appropriate for that case.
Some links to get you started:
Can I use SQL functions in NHibernate QueryOver?
NHibernate QueryOver SQLFunction in where clause
Can NHibernate's QueryOver syntax select MAX() of an SqlFunction?

Related

Using SQL instead of Linq to query database and return Json

I am developing an application using ASP.Net MVC and AngularJS. I am not familiar with linq and honestly I don't like it. But I am very familiar with SQL and I can perform complex queries. So, my question is, I want you to look at the below code from my MVC controller:
public JsonResult GetSupervisor()
{
var db = new scaleDBEntities();
return this.Json((from userObj in db.Users
select new
{
supervisorId = userObj.Id,
supervisorfName = userObj.usrFirstName,
supervisorlName = userObj.usrLastName,
})
, JsonRequestBehavior.AllowGet
);
}
How can I change the link query into SQL query?
I believe that I can do something like this:
var blogNames = db.Database.SqlQuery<string>("SELECT Name FROM dbo.Blogs").ToList();
So, if this is right, how can i use in in my return this.Json() for my angular?
Using the example you provided, something like this should work:
return this.Json(new {blogNames});
You're just creating an anonymously-typed object that the JSON serializer can use to produce an object like this:
{
"blogNames": ["blog one", "blog two"]
}
It'll be more complicated if you're trying to produce more complex results from a more complex query. But, well, that's what an ORM is for. I'd echo Gert Arnold's advice to embrace LINQ, rather than just deciding you don't like it because you're not used to it.

NHibernate QueryOver projection on many-to-one

I am trying to get a QueryOver working using a Projection on a many-to-one.
The class "Post" has a property many-to-one "Creator".
Using
session.QueryOver(Of Post).
Select(Projections.
Property(of Post)(Function(x) x.Creator).
WithAlias(Function() postAlias.Creator)).
TransformUsing(Transformers.AliasToBean(Of Post)()).
List()
works BUT each creator is retrieved by a single query rather than using a join like it is done when not using a select/projection. So if there are 5 posts with 5 different creators, 6 queries will be run 1 for the list of posts and 5 for the creators.
I tried to get it working using a JoinAlias but nothing really did the job.
I already searched for a solution, but all solutions I found did use the Linq-Provider which does not really fit since the actual "field list" is passed via a parameter.
Does anyone know if there is a solution to this other than the linq provider?
There is a solution, we can use projections for many-to-one and then custom result transformer.
DISCLAIMER: I can read VB syntax but do not have enough courage to write... I expect that you can read C# and convert it into VB....
So we can have projection like this:
// aliases
Post root = null;
Creator creator = null;
// projection list
var columns = Projections.ProjectionList();
// root properties
columns.Add(Projections.Property(() => root.ID).As("ID"));
columns.Add(Projections.Property(() => root.Text).As("Text"));
// reference properties
columns.Add(Projections.Property(() => creator.ID).As("Creator.ID"));
columns.Add(Projections.Property(() => creator.FirstName).As("Creator.FirstName"));
// so our projections now do have proper ALIAS
// alias which is related to domain model
// (because "Creator.FirstName" will be use in reflection)
var query = session.QueryOver<Post>(() => root)
.JoinAlias(() => root.Creator, () => creator)
.Select(columns)
Now we would need smart Transformer, our own custome one (plugability is power of NHibernate). Here you can find one:
public class DeepTransformer
And we can continue like this
var list = query
.TransformUsing(new DeepTransformer<Post>())
.List<Post>()
Check also this:
Fluent NHibernate - ProjectionList - ICriteria is returning null values
NHibernate AliasToBean transformer associations

Linq order by with a field to retrieve dynamically in vb.net

I have a object Ob with several fields f1,..,fn (of different types).
Now a list of object is shown in a GridView and I need to implement the sorting method.
The real problem is:
how can I run
(from ob in Ob_list orderby ob.f1 ascending)
when the sorting field is represented by a string (i.e. "f1")?
Unfortunately I am not able to get it with the reflection (I am not able to do something like ob.GetType().GetField("f1"), this is not mapped into sql code).
I have several fields to possibly sort the rows, which is the best&fastest approach to this?
Thank you very much!
LINQ execution is deferred until you actually enumerate over the results or access the "count", etc. Because of this, you can build up your LINQ statement in stages.
The below code is done in C#, but I'm sure the equivalent is possible in VB.NET.
First setup your basic query:
var query = (from ob in Ob_list);
At this point, nothing has actually gone to the database due to deferred execution.
Next, conditionally add your order by components:
if (sortField == "f1")
{
query = query.OrderBy(o => o.f1);
}
else if (sortField == "f2")
{
query = query.OrderBy(o => o.f2);
}
else
{
//...
}
And finally, collect your results
foreach (var item in query)
{
// Process the item
}
I've found this question: How do I specify the Linq OrderBy argument dynamically?
I'm using Entity Framework, so the first answer did not solved my problem. The second one however, worked great!
Hope it helps!

queryover and is in a list filter

I dont really understand how I can perform this query using nhibernate queryover, I currently have:
var users= _session.QueryOver<User>().Future();
var comps = _session.QueryOver<UserCompetency>()
.Where(x => users.Any(match => x.UserID == match.UserID)).Future();
an exception keeps getting thrown, using linq to sql this works perfectly fine?
QueryOver is not LINQ. It does not support arbitrary expressions.
Use the Query extension method if that's what you need.

LLBLGEN: Linq to LLBGEN don't work

I want to make custom select from the database table using Linq. We use LLBGEN as ORM solution.
I can't do LINQ query to Entities Collection Class unless I call GetMulti(null) method of it.
Is it possible to do LINQ query to LLBGEN without extracting all table first?
BatchCollection batches = new BatchCollection();
BatchEntity batch = batches.AsQueryable()
.Where(i => i.RegisterID == 3)
.FirstOrDefault(); // Exception: Sequence don't contains any elements
batches = new BatchCollection();
batches.GetMulti(null); // I don't want to extract the whole table.
BatchEntity batch = batches.AsQueryable()
.Where(i => i.RegisterID == 3)
.FirstOrDefault(); //Works fine
To query your database using LINQ (which is different from operating on an enumerable collection using the LINQ syntax) you have to use the LinqMetaData provider that comes with LLBLGen in the yourrootnamespace.Linq assembly. Once you add this assembly to your project you can use something like this to create your db query: (from the LLBL documentation)
LinqMetaData metaData = new LinqMetaData();
var q = from c in metaData.Customer
where c.Country=="USA"
select c;
In your example above you are using LINQ syntax to perform a where clause on a collection, but this does not have anything to do with LLBL or executing a query on the database. That is why it will not work with the empty collection, but does work on the filled collection.
Look more into LinqMetaData for the specifics of querying your db using LINQ to LLBLGen.