I have this scenario:
var query = Session.QueryOver<T>()
var criteria = query.UnderlyingCriteria.SomethingThereAddCriterion()
How can I transform criteria back to IQueryOver()?
Your criterias has been added to the UnderlyingCriteria of query. So you don't need to transform criteria to IQueryOver(). Just use query again.
Related
I've been working on improving performance for our .NET core API with EF 5.0.11 by reducing the projection of our queries, but I'm currently stuck with the following scenario:
I improved the projection of the queries like this:
var employeeEmailQuery = context.Employee
.Where(e => e.Active == true)
.Select(e => new EmployeeEmailView
{
Name = e.FullName,
Email = e.Email
});
This reduces the select query to just the two columns I need instead of a SELECT * on 80+ columns in the database.
In my database, I also have columns with translated descriptions. It looks like this:
What I would like to do is select the relevant translated description, based on the current culture, so I added the following code:
var culture = CultureInfo.DefaultThreadCurrentUICulture;
var employeeEmailQuery = context.Employee
.Where(e => e.Active == true)
.Select(e => new EmployeeEmailView
{
Name = e.FullName,
Email = e.Email,
this.SetDescription(e, culture);
});
The SetDescription method checks the culture and picks the correct column to set a Description property in the EmployeeEmailView. However, by adding this code, the query is now once again doing a SELECT *, which I don't want.
Does anybody have an idea on how to dynamically include a select column using EF without rewriting everything into raw SQL?
Thanks in advance.
I think the only way is to use an Interceptor to modify the query, or dynamically generate the EF IQueryable with Expressions.
Is it possible to prevent the EF from making two queries in the following query?
var regitriesNames =
from registryView in registryViewRepository.GetAll()
where (
from registryReport in registryReportRepository.GetAll()
where registryReport.ReportId == reportId
select registryReport.RegistryViewId
).Contains(registryView.Id)
select registryView.Name;
The query works just fine. The only thing that I would like to avoid is the double use of the GetAll().
So, is it possible to imrove the query somehow?
I have two entities: RegistryView and Report and I have an entity which represents the many to many relationship between them RegistryReport.
Please check this one.
Code
var lstdata = registryViewRepository.GetAll();
var regitriesNames = from registryView in lstdata
where (
from registryReport in lstdata
where registryReport.ReportId == reportId
select registryReport.RegistryViewId
).Contains(registryView.Id)
select registryView.Name;
How could these two queries be merged in Rails 5?
Event
.where(starts_at: date.beginning_of_day..date.end_of_day)
.where(kind: "opening")
Event.where("cast(strftime('%w', starts_at) as int) = ?", date.wday)
.where(kind: "opening")
.where(weekly_recurring: true)
I need to take all these events in one query for performance.
Thanks for the help
If you want to combine results then
Event.where(starts_at: date.beginning_of_day..date.end_of_day).where(kind: "opening").where("cast(strftime('%w', starts_at) as int) = ?", date.wday).where(kind: "opening").where(weekly_recurring: true)
If you want two separate results in one query, i dont think active records has such method.
I have always easier to write complex queries such as the one you need directly in SQL; It will be faster for you to write than trying to shoehorn it into ActiveRecord.
In your case, I would do something like this:
query = "starts_at between #{date.beginning_of_day} and #{date.end_of_day}
and kind = 'opening'
and weekly_recurring = true
and cast(strftime('%w', starts_at) as int) = #{date.wday}"
Event.where(query)
I find this approach easier and more maintanable.
I populating a Primefaces datatable lazily with a custom complex dynamic query built using CriteriaBuilder, performing a SQL query on a database.
For that I need to perform a record count using this query and I also need to run the query itself to get the record in the specified interval for the datatable.
So I thought I could do something like this:
CriteriaBuilder criteriaBuilder = this.getEntityManager().getCriteriaBuilder();
CriteriaQuery<Object> criteriaQuery = criteriaBuilder.createQuery();
Root<RSip> from = criteriaQuery.from(RSip.class);
Path<Long> eSipss = from.join("idESip").get("ss");
CriteriaQuery<Object> select = criteriaQuery.select(from);
List<Predicate> predicates = new ArrayList();
//Many predicates added according to user end
predicates.add(...);
predicates.add(...);
predicates.add(...);
//The query is now ready
select.where(predicates.toArray(new Predicate[predicates.size()]));
//but I need also to perform the record count using SQL Count as the dataset returned can be very large
CriteriaQuery<Object> selectCount = criteriaQuery.select(criteriaBuilder.count(fromCount));
//and then perform both selects like this:
//Record Count:
TypedQuery<Object> typedQueryCount = this.getEntityManager().createQuery(selectCount);
List<Object> recordCount = typedQueryCount.getResultList();
//Query:
TypedQuery<Object> typedQuery = this.getEntityManager().createQuery(select);
List<Object> records = typedQuery.getResultList();
The problem is that on this second query, it returns me the record count also and not the actual records...what can I be doing wrong?
If there is some other way to do this I'm happy to read your answer!
Doman:
class Action
Products: IList of class ActionProducts:
Category: class Category
Products: IList of class Product
Now, I want this:
var products = from a in Session.Linq<Action>()
from ap in a.Products
from p in ap.Category.Products
where a.Name == name
select p;
And this Linq actually works but: 1. produces select for all tables instead of only Products 2. produces left outer joins, not inner 3. Distinct() on the query doesn't work (though ToList().Distinct() works).
Also can be done with SelectMany(a => a.Products).SelectMany(ap => ap.Category.Products) but it doesn't work at all with current NHibernate.Linq.
So I want to use ICriteria. But I can't see how do I return product, not action?
ICriteria criteria = Session.CreateCriteria(typeof(Action))
.Add(Expression.Eq("Name", name))
.CreateAlias("Products", "ap")
.CreateAlias("ap.Category.Products", "p")
.SomehowReturnMeOnly("p");
So how do I SomehowReturnMeOnly("p")? So that I can do
return criteria.List<Product>();
which will fail because ICriteria selects Actions, not Products?
I may consider HQL but I actually doesn't like string queries... Just for example, here's the HQL that works and produces exactly the SQL that I need:
IQuery query = Session.CreateQuery("select distinct p from Action a inner join a.Products as ap inner join ap.Category.Products as p");
return query.List<Product>();
Now, something similar can be done (keeping in mind that CreateAlias can only do 1 level) using
DetachedCriteria dq = DetachedCriteria.For<Action>()
.Add(Expression.Eq("Name", name))
.CreateAlias("Products", "ap")
.CreateAlias("ap.Category", "c")
.CreateAlias("c.Products", "p")
.SetProjection(Projections.Property("p.Id"));
ICriteria criteria = Session.CreateCriteria(typeof(Product))
.Add(Subqueries.PropertyIn("Id", dq));
return criteria.List<Product>();
This works and passes test, but produces "SELECT FROM products WHERE id in (subquery)" which may be even better (no DISTINCT required) but is not what I wanted to achieve. Seems like Criteria API is very, very restrictive. So we have:
HQL with string-query drawbacks
Criteria API with lots of restrictions and sometimes awful code to achieve simple results
NH-Linq which looks very promising but is incomplete now.
So I guess I'll stick with HQL until Linq is ready.
You need to use Projections, something like this:
ICriteria criteria = Session.CreateCriteria(typeof(Action))
.Add(Expression.Eq("Name", name))
.CreateAlias("Products", "ap")
.CreateAlias("ap.Category.Products", "p")
.SetProjection(Projections.Property("ap.Category.Products"))
.List<Product>();
Have a look at the nhibernate docs here for some examples.
Well, after thinking about Chris' answer... I tried this and it seemed to work:
ICriteria criteria = Session.CreateCriteria(typeof(Action))
.Add(Expression.Eq("Name", name))
.CreateAlias("Products", "ap")
.CreateAlias("ap.Category", "c")
.SetProjection(Projections.Distinct(Projections.Property("c.Products")));
Looks like NHibernate doesn't allow deep nesting of projection properties which is strange. And it doesn't work either, looking at generated SQL I see that it only selects
SELECT distinct c2_.Id as y0_ FROM ... Categories c2_ ...
i.e. it doesn't really fetch products, which makes my unit test to fail because returned list contains only nulls instead of Product instances.