I have a question on criteria:
How can i use a Criteria (or similar) that filters and/or do whatever with another criteria?
Something like:
select clients.* from
(select * from clients) as clients
The real problem is something else, but achieving this behaviour would be terrific...
(btw, both java and .net are welcome to help)
thanks
It can't be done, AFAIK. The tutorial about HQL says:
Note that HQL subqueries can occur only in the select or where clauses.
I can't find same statement about Criteria, but in API the only way to create criteria is to give mapped type. There is support for subqueries but only in where clause. Here is javadoc.
Your FROM clause needs to be a mapped object. You could do a subselect inside the WHERE clause... something like:
select c from clients c where c.id in (select c2.id from clients c2)
It would help if you could give a better example. The example you gave can be reduced down to the following HQL:
"from clients"
...which isn't terribly useful.
You could try adding a NHibernate.Criterion.InExpression to your criteria.
Found an example on this blog:
http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/08/26/parameter-lists-in-nhibernate.aspx
i'm not sure i understand your question correctly, but if you want to do a select on a list of objects, you can use the subqueries with DetachedCriteria. I use it all the time, especially for paging objects while creating a left outer join, which could lead me to incorrect number of entities.
Imagine you've got users who buy products, with a relationship many-many:
Dim dc As DetachedCriteria = DetachedCriteria.For(GetType(User)).SetFirstResult(pageNumber * itemsPerPage).SetMaxResults(itemsPerPage)
Session.CreateCriteria(GetType(user)).Add(Subqueries.PropertyIn("Id", dc)).CreateAlias("ProductsBought", "pb", NHibernate.SqlCommand.JoinType.LeftOuterJoin)
Thom's right, perhaps you should be more precise...
Related
First of all I'm sorry because this is the second time that I write this question but before was bad explained and now is close.
I'm doing a linq query for a search page for a CRM data base, and wrtiting a normal query like below is not working, I'm getting the exception:
[System.ServiceModel.FaultException<Microsoft.Xrm.Sdk.OrganizationServiceFault>] = {"'Contact' entity doesn't contain attribute with Name = 'title'."}
For a join query, that in the clause Where was something like r.Name == "Me" && j.LastName == "He" I had to did the query with two Where clauses, because I was getting the same exception as above, saying that table 'r' doesn't have 'LastName' attributte.
var cms = from i in aux_pr
join cal in Contact on i.aux_CallerRequestorID.Id equals cal.ContactId.Value
join sub in Subject on i.aux_ClassificationID.Id equals sub.SubjectId
where cal.FullName.Contains(searchTerm) ||
sub.Title.Contains(searchTerm)
In this case, how can I do this query. Thanks in advance!
I want to comment what have I learned and the solution that I have found to my problem hoping could help some one. There are some limitations in CRM LINQ, as explained here
The first that I found, having an entity reference like this:
CrmEntityReference Caller
{
Guid ID;
string name;
}
I can select Caller.name but I CAN'T have Caller.name in the where clause. Solution for this -> Join the table
The second limitation, is when we have joins in the query, we can have different tables in the where if they are an AND predicate, we have to write two clauses where like this:
where cal.FullName.Contains(searchTerm)
where sub.Title.Contains(searchTerm)
But the problem comes when instead of an AND we need use an OR predicate, the only solution we have is do two queries and after do an Union of these queries.
I have four queries for a call that could be done just with one, now in developing stage performance is good due to the amount of records, but we'll see in testing stage how this work.
try to create two different filters..
var cms = from i in aux_pr
join cal in Contact on i.aux_CallerRequestorID.Id equals cal.ContactId.Value
join sub in Subject on i.aux_ClassificationID.Id equals sub.SubjectId
where cal.FullName.Contains(searchTerm) ||
where sub.Title.Contains(searchTerm)
Currently I'm running some code and got some question about this. Below are the code listings of two LINQ to Entites queries.
Code listing A:
IQueryable list =
from tableProject in db.Project
select new {StaffInCharge = (
from tableStaff in db.Staff
where tableStaff.StaffId == tableProject.StaffInChargeId
select tableStaff.StaffName)};
Code listing B:
IQueryable list =
from tableProjectin db.Project
join tableStaff in db.Staff
on tableProject.StaffInChargeId
equal tableStaff.StaffId
select new {StaffInCharge = tableStaff.StaffName};
What I want to figure out is which one will be better and faster if I have to select many column from many others table.
Thanks.
this is the comment from #Tim Schmelter
"The article(actually my SO-Question) relates to LINQ-To-DataSet what is based on LINQ-To-Objects. Linq to SQL or Linq to Entities might be optimized by the DBMS in that way that a where clause has the same performance as a join."
and the link is
Why is LINQ JOIN so much faster than linking with WHERE?
i think it is very useful.
I'm fairly new to nHibernate having come from an EF background and I'm struggling with the following query :
_patientSearchResultModel = (from patient in _patientRepository.Query(patientSearch.BuildPatientSpecification())
join admission in _admissionRepository.Query(patientSearch.BuildAdmissionSpecification())
on patient.Id equals admission.Patient.Id
orderby admission.AdmissionDate
select new PatientSearchResultModel(patient.Id,
admission.Id,
false,
_phaseTypeMapper.GetPhaseTypeModel(admission.PhaseType),
patient.Last, patient.First,
admission.InPatientLocation,
admission.AdmissionDate,
admission.DischargeDate,
admission.RRI,
null,
admission.CompletionStatus,
admission.FollowupStatus)).ToList();
The intent of this query is to allow users to filter the two queries on parameters built up using the two Build???Specification functions and return the resultset. There could be many admission records and I would only like one PatientSearchResultModel per patient object, with the admission object being the newest one by Admission Date.
These objects are coming from nHibernate and it keeps return a Not Supported exception. There is also an association between Patient and Admissions thus : Patient.Admissions but i couldn't figure out how to then add the query filters return from the function Build???Specifications.
I'd be really grateful if someone could point me in the right direction; am I up against the Linq provider implementation here in nHibernate and need to move to Criteria or is it my Linq query ?
If anyone has any links or suggestions for good books or other learning materials in this area that would also be really helpful too.
I see several potential problems:
If you're using NHibernate 2.x + Linq2NHibernate explicit joins like that are not supported; in other versions they're just considered a smell.
I dont think NHibernate supports calling parameterized constructors in select clauses
I'm very sure NHibernate does not support calling instance methods in the select lambda
I'd suggest using the lambda syntax and SelectMany to alleviate potential join issues. Points #2 & #3 can be solved by projecting into an anonymous type, calling AsEnumerable then projecting into your model type.
Overall I'd suggest restructuring your code like:
var patientSpec = patientSearch.BuildPatientSpecification();
var admissionSpec = patientSearch.BuildAdmissionSpecification();
_patientSearchResultModel = _patientRepository.Where(patientSpec)
.SelectMany(p=>p.Admissions).Where(admissionSpec)
.Select(a=> new {
PatientId = a.Patient.Id,
AdminssionId = a.Id,
a.PhaseType,
a.Patient.Last,
a.Patient.First,
a.InPatientLocation,
a.AdmissionDate,
a.DischargeDate,
a.RRI,
a.CompletionStatus,
a.FollowupStatus
}).AsEnumerable()
.Select(x=> new PatientSearchResultModel(x.PatientId, x.AdmissionId ...))
.ToList();
Divide your query into parts and check which part runs and which doesn't.
My take on this is that select new ... is not supported in Linq to nHibernate.
I would recomend using something else, because it is simply too imature and feature-less to use seriously.
As with most popular LINQ-to-Database query providers, NHibernate will try to translate the whole query into a SQL statement to run against the database. This requires that all elements of your query are possible to express in the SQL flavour you're using.
In your query, the select new statement cannot be expressed in SQL, because you're making a call to the constructor of your PatientSearchResultModel class and are making a call to a GetPhaseTypeModel method.
You should restructure your query to express what you want to execute on the SQL database, then call AsEnumerable() to force the remainder of the query to be evaluated in-memory. After that call, you can call the constructor of your class and any .NET methods, and they will be executed as native code.
This query is too complex to describe it using Linq. It would give wrong result finally (if Patient has more than one admission records, result would have duplicate entries).
I see two steps for solution:
1) At development stage, use in-memory query. So, take Patients using ToList() first (query db at this moment). Some predicates (Patient filter like MRN, First, Last) could be used at this stage.
And then do search in-memory. Not performance, but working solution. Mark it for refactor to optimize later.
2) Finally, use NHibernate IQuery (ISQLQuery) and build sql query manually to make sure it would work as expected and work fast enough on SQL Server side. This is just read-only query and do not require Nhibernate query engine (Linq to Nhibernate) at all.
One of the things that you have beaten into you as a junior developer is that you never, ever do a "SELECT *" on a data set, as it is unreliable for several reasons.
Since moving over to Linq (firstly Linq to SQL and then the Entity Framework), I have wondered if the Linq equivalent is equally frowned upon?
Eg
var MyResult = from t in DataContext.MyEntity
where t.Country == 7
select t;
Should we be selecting into an anonymous type with just the fields we want explicitly mentioned, or is the catch all select now acceptable for LinqToSql et al because of the extra stuff surrounding the data they provide?
Regards
Moo
It's not frowned upon, it's determined by your use case. If you want to update the result and persist it then you should select t, however if you don't want to do that and are just querying for display purposes you can make it more efficient by selecting the properties you want:
var MyResult = from t in DataContext.MyEntity
where t.Country == 7
select new { t.Prop1, t.Prop2 };
This is for a few reasons. The population of an anonymous type is slightly faster, but more importantly it disables change tracking...because you can't persist an anonymous type, there's no need to track changes to it.
Here's an excellent rundown of the common performance areas like this that's great when starting out. It includes a more in-depth explanation of the change tracking I just described as well.
select t in this case s selecting all fields from a known type. It is strongly typed and less subject to the same errors found in SQL.
For example in SQL
INSERT INTO aTable
SELECT * FROM AnotehrTable
could fail if AnotherTable changed, however in Linq / .Net this situation doesn't appear.
If you are joining multiple tables, then you can't do a select * in Linq, you would have to create an anonymous type with all types contained within.
The reason for avoiding SELECT * is that the underlying database might change and therefore column orders might change which could result in bugs in your data access layer.
You are not performing a SELECT * from your database, you are just saying that you want "t" and everything that goes with it. There is nothing wrong with that if that is truly what you need.
I would say what you are doing is the equivalent to a SELECT * statement. It is better to return only the fields you require e.g.
var myResult = from t in DataContext.MyEntity
where t.Country == 7
select new T
{
Field1 = t.Field1,
Field2 = t.Field2
}
You should still explicitly state what you want to select. If you select all, you are still pulling down far more data than you need and as new things are added, you will unnecessarily pull those as well. In general, a best practice is to pull only what you need.
Using LINQ will not alleviate the performance hit of getting extra fields.
However, it is impossible to generate a SELECT * FROM ... using LINQ to SQL.
Your code will generate a SELECT statement that explicitly names all of the columns defined in your model; it will ignore any changes to the database.
However, performance is still a concern, so you should use an anonymous type if you're only using some of the columns.
It may be necessary to do it as in the example, especially if what needs to be done is a change to the row(s).
in SQL select * is different than linq because linq will always return the same number of columns (as defined in the dbml).
I dont't know how to describe the title better (so feel free to change) but essntial I want to produce the equivilent of the following statement in LINQ to SQL:
select * from products where category in ('shoes','boots')
The fields will be coming from the query string essentially (more secure than this but for ease of explanation) i.e
string[] myfields = request.querystring["categories"].split(',');
Thanks
Yes, you use Contains:
db.Products.Where(product => myFields.Contains(product.Category))
aka
from product in db.Products
where myFields.Contains(product.Category)
select product
As other have mentioned, yes it does using the .Contains method. To benefit the other random people that may arrive here via Bing (or any of the other search engines): Linq-To-Entities does not support the .Contains method in the current version. However, with a simple extension method, you can do so:
http://george.tsiokos.com/posts/2007/11/30/linq-where-x-in/
In theory you would use contains:
var productList = from product in context.Products
where myfields.contains(product.category)
select product
However you'll need to test this - I seem to recall there being a bug in the Linq2Sql optimizer when trying to deal with List<> and array values being used like this (it may have only occured if you tried to cast them as IQueryable)