I would create a QueryOver like this
SELECT *
FROM Table
WHERE Field IN (1,2,3,4,5)
I've tried with Contains method but I've encountered the Exception
"System.Exception: Unrecognised method call: System.String:Boolean Contains(System.String)"
Here my code
var qOver = _HibSession.QueryOver<MyModel>(() => baseModel)
.JoinAlias(() => baseModel.Submodels, () => subModels)
.Where(() => subModels.ID.Contains(IDsSubModels))
.List<MyModel>();
I've found the solution!! :-)
var qOver = _HibSession.QueryOver<MyModel>(() => baseModel)
.JoinAlias(() => baseModel.Submodels, () => subModels)
.WhereRestrictionOn(() => subModels.ID).IsIn(IDsSubModels)
.List<MyModel>();
You can try something like this:
// if IDsSubModels - array of IDs
var qOver = _HibSession.QueryOver<MyModel>()
.Where(x => x.ID.IsIn(IDsSubModels))
You don't need a join in this situation
This works and is more elegant
var Strings = new List<string> { "string1", "string2" };
var value = _currentSession
.QueryOver<T>()
.Where(x => x.TProperty == value)
.And(Restrictions.On<T>(y=>y.TProperty).IsIn(Strings))
.OrderBy(x => x.TProperty).Desc.SingleOrDefault();
where T is a Class and TProperty is a property of T
Related
I have a line like so:
var lstOfIds = db.TBL_AssocIncidentSpecialCat
.Where(x => x.IncidentId == incidentVm.ID)
.Select(t => t.SpecialCategoriesId)
.ToList();
This line gathers me a list of of the SpecialCategoriesIds. Then I have to do this:
incidentVm.LstSpecialCategories = db.TBL_SpecialCategories
.Where(x => lstOfIds.Contains(x.Id))
.Select(t => t.SpecialCategory)
.ToList();
Is there a way to combine these two lines into one? Even though it's only two lines of code.. I feel as though having to grab the Ids first then having to grab the associated property based on the Id is just an extra step and could be shortened to just one line. But I may be wrong.
Any help is appreciated.
UPDATE
incidentVm.LstSpecialCategories = db.TBL_AssocIncidentSpecialCat
.Where(x => x.IncidentId == incidentVm.ID)
.Join(
db.TBL_SpecialCategories,
x => new{Id = x.SpecialCategoriesId},
t => new{Id = t.Id},
(x,t) => {return t.SpecialCategory}
);
I am getting red squiggly under last part in Join:
A lambda expression with a statement body cannot be converted to an expression tree
You can combine the two lines using Join. Something like,
var result = db.TBL_AssocIncidentSpecialCat
.Join(
db.TBL_SpecialCategories,
ais => new { Id = ais.IncidentId },
sc => new { Id = sc.Id },
(ais, sc) => { return sc; }
)
.ToList();
C# Fiddle for this.
Update with Where Clause: You should use your Where condition after the Join.
var result = db.TBL_AssocIncidentSpecialCat
.Join(
db.TBL_SpecialCategories,
ais => new { Id = ais.IncidentId },
sc => new { Id = sc.Id },
(ais, sc) => new { ais = ais, sc = sc }
)
.Where(x => x.ais.IncidentId == 1)
.Select(y => y.sc)
.ToList();
You can try a LINQ query-style join:
incidentVm.LstSpecialCategories = (from aispc in db.TBL_AssocIncidentSpecialCat
join spc in db.TBL_SpecialCategories
on aispc.SpecialCategoriesId equals lspc.Id
where aispc.IncidentId == incidentVm.ID
select lspc.SpecialCategory).ToList();
I was able to figure this out with the help of some answers and me testing it on my own. Here is my solution:
incidentVm.LstSpecialCategories = db.TBL_AssocIncidentSpecialCat
.Where(t => t.IncidentId == incidentVm.ID)
.Join(db.TBL_SpecialCategories,
ik => ik.SpecialCategoriesId,
ok => ok.Id,
(ik, ok) => ok.SpecialCategory
)
.ToList();
Thank you for all of your help.
I'm doing a query over two different tables.
In the first query, i get some Ids that I then have to check in another table.
Then I do the first query again with the result of the second query.
This can't be the best way to do this.
But I haven't found a good way to solve it. So some help would be appreciated.
IntOrderInvoiceCostOut y = null;
var list = session.QueryOver<IntOrderInvoiceCostOut>(() => y)
.Where(x => x.IntegrationHandleDate == null)
.Select(Projections.Distinct(Projections.Property(() => y.Externalid)))
.List<string>();
var nonPreliminaryOrders = session.QueryOver<RefImplOrderEntity>()
.WhereRestrictionOn(x => x.ExternalId).IsIn(list.ToList())
.Where(x => x.StatusTypeId != 95)
.Select(x => x.ExternalId)
.List<string>();
var finalList = session.QueryOver<IntOrderInvoiceCostOut>()
.WhereRestrictionOn(x => x.Externalid).IsIn(nonPreliminaryOrders.ToList())
.Where(x => x.IntegrationHandleDate == null)
.OrderBy(x => x.IntegrationCreateDate)
.Asc
.List();
The code works...but i't really ugly.
you could use detacheCriteria for this. I have omitted couple of conditions and you might have to twick a bit as per your requirement.
for example
IntOrderInvoiceCostOut y = null;
var list = QueryOver.Of<IntOrderInvoiceCostOut>(() => y)
.Where(x => x.IntegrationHandleDate == null)
.Select(Projections.Distinct(Projections.Property(() => y.Externalid)))
.DetachedCriteria;
var nonPreliminaryOrders = QueryOver.Of<RefImplOrderEntity>()
.Where(Subqueries.PropertyIn(nameof(RefImplOrderEntity.ExternalId), list));
.Select(x => x.ExternalId)
.DetachedCriteria
var finalList = session.QueryOver<IntOrderInvoiceCostOut>()
.Where(Subqueries.PropertyIn(nameof(IntOrderInvoiceCostOut.ExternalId), nonPreliminaryOrders));
.List();
I have the following nHibernate query that select a course based on its course id and then return selected fields for the course object on the initial fetch, and the query executes with no issues.
MatchMode option = ...
CourseItem courseAlias = null;
TeacherItem teacherAlias = null;
var query = session.QueryOver<CourseItem>()
.JoinAlias(c => c.Teacher, () => teacherAlias)
.Where(c => c.CourseID.IsInsensitiveLike(strNumber, option))
.SelectList(list => list
.Select(c => c.CourseID).WithAlias(() => courseAlias.CourseID)
.Select(c => c.IsActive).WithAlias(() => courseAlias.IsActive)
.Select(c => c.CourseDesc).WithAlias(() => courseAlias.CourseDesc)
.Select(c => c.Teacher).WithAlias(() => courseAlias.Teacher))
.TransformUsing(Transformers.AliasToBean<CourseItem>())
.List<CourseItem>();
I wanted to go a step further with the query to only return a partial teacher object, let's say i just wanted to return the ID and Name. So, I updated the projected list to as follows:
var query = session.QueryOver<CourseItem>()
.JoinAlias(c => c.Teacher, () => teacherAlias)
.Where(c => c.CourseID.IsInsensitiveLike(strNumber, option))
.SelectList(list => list
.Select(c => c.CourseID).WithAlias(() => courseAlias.CourseID)
.Select(c => c.IsActive).WithAlias(() => courseAlias.IsActive)
.Select(c => c.CourseDesc).WithAlias(() => courseAlias.CourseDesc)
.Select(c => c.Teacher.ID).WithAlias(() => courseAlias.Teacher.ID)
.Select(c => c.Teacher.Name).WithAlias(() => courseAlias.Teacher.Name))
.TransformUsing(Transformers.AliasToBean<CourseItem>())
.List<CourseItem>();
The query doesn't work because nHibernate has no idea how to resovled based on Teacher.ID and Teacher.Name. Any thoughts on whether it's possible to NOT fetch the entire child object back to a parent object?
I've tried the following query and it works this is not my fully desired outcome
var query = session.QueryOver<CourseItem>(() => courseAlias)
.JoinAlias(() => courseAlias.Teacher, () => teacherAlias)
.Where(() => courseAlias.CourseID.IsInsensitiveLike(strNumber, option))
.SelectList(list => list
.Select(() => courseAlias.CourseID)
.Select(() => courseAlias.IsActive)
.Select(() => courseAlias.CourseDesc)
.Select(() => teacher.ID)
.Select(() => teacher.Name))
.List<object[]>();
I can query the right values but unable to transform it back correctly to the Course / teacher data type.
Any thoughts?
thanks!
We can indeed use custom transformer. There is one, which I am using for a really very very deep projections (inlcuding dynamic objects - 5.1.13. component, dynamic-component)
DeepTransformer<TEntity>
Take it (if needed adjust it) and your final query could be like this
// just the last lines are different
var query = session.QueryOver<CourseItem>()
.JoinAlias(c => c.Teacher, () => teacherAlias)
.Where(c => c.CourseID.IsInsensitiveLike(strNumber, option))
.SelectList(list => list
.Select(c => c.CourseID).WithAlias(() => courseAlias.CourseID)
.Select(c => c.IsActive).WithAlias(() => courseAlias.IsActive)
.Select(c => c.CourseDesc).WithAlias(() => courseAlias.CourseDesc)
// the native WitAlias would not work, it uses expression
// to extract just the last property
//.Select(c => c.Teacher.ID).WithAlias(() => courseAlias.Teacher.ID)
//.Select(c => c.Teacher.Name).WithAlias(() => courseAlias.Teacher.Name))
// so we can use this way to pass the deep alias
.Select(Projections.Property(() => teacherAlias.ID).As("Teacher.ID"))
.Select(Projections.Property(() => teacherAlias.Name).As("Teacher.Name"))
// instead of this
// .TransformUsing(Transformers.AliasToBean<CourseItem>())
// use this
.TransformUsing(new DeepTransformer<CourseItem>())
And in case, that your aliases do match to property names, that transformer will built the object tree...
I'm using NHibernate first time and in this line it throws exception for me
var total = session
.QueryOver<Comment>().Where(p => p.Entry.Author == username)
.ToRowCountQuery()
.FutureValue<int>();
var results = session
.QueryOver<Comment>().Where(p => p.Entry.Author == username)
.Fetch(x => x.Entry).Eager()
.OrderBy(x => x.Posted).Desc()
.Skip(skip)
.Take(take)
.List();
The Exception is
could not resolve property: Entry.Author of: FunnelWeb.Model.Comment
I guess, the problem is that Entry object doesn't loaded here. How can I do that trick with Nhibernate?
QueryOver is just a strongly-typed wrapper for Criteria, and doesn't allow implicit deep references.
You'd have to use:
session.QueryOver<Comment>()
.JoinQueryOver(x => x.Entry)
.Where(x => x.Author == username)
Or you can use Query<> instead (LINQ) which will work with the syntax you've tried.
You'd need to JoinAlias or JoinQueryOver. I have an example below on how to use Future queries...
Entry entryAlias = null;
var q = session.QueryOver<Comment>()
.JoinAlias(x => x.Entry, () => entryAlias)
.Where(() => entryAlias.Author == username);
var totalFuture = q.ToRowCountQuery().FutureValue<int>(); //ToRowcountQuery clones the query, we can reuse it for results
var resultsFuture = q
//.Fetch(x => x.Entry).Eager() //already joined
.OrderBy(x => x.Posted).Desc()
.Skip(skip)
.Take(take)
.Future<Comment>();
var results = resultsFuture.ToList(); //both future queries are executed in the same batch
var total = totalFuture.Value;
Hi gyus
I'm writing here so....I've a problem :-)
Here my situation:
Table A (Category) {ID, List, List }
Table B (CategoryLanguage) {IDCategory, IDLanguage, Description}
Table C (SubCategory) {IDCategory, ID, List }
Table D (SubCategoryLanguage) {IDSubCategory, IDLanguage, Description}
Here my QueryOver (with Aliases) code
Category Cat = null;
CategoryLanguage catLang = null;
SubCategory subCat = null;
SubCategoryLanguage subCatLang = null;
var qOver = _HibSession.QueryOver<Category>(() => Cat)
.Left.JoinAlias(() => Cat.Languages, () => catLang)
.Where(() => catLang.IDLanguage == IDLanguage)
.Left.JoinAlias(() => Cat.SubCategories, () => subCat)
.Left.JoinAlias(() => subCat.Languages, () => subCatLang)
.Where(() => subCatLang.IDLanguage == IDLanguage)
.OrderBy(() => Cat.ID).Asc
.List<Category>();
With this Query, NHibernate doesn't filter the Languages fields and when I loop into the subCategories (to print out on my view the tree Category=>SubCategory ) it launches a Query for every subCategory!! (I saw it using NHibernate Profiler)
I don't use Lazy Loading but using JoinAlias I expected to see all data joined.
Anyone can help me?
Thank you!
Not sure if it helps but in some of the queries I've created using QueryOver I've specified the fetch mode e.g.
Category Cat = null;
CategoryLanguage catLang = null;
SubCategory subCat = null;
SubCategoryLanguage subCatLang = null;
var qOver = _HibSession.QueryOver<Category>(() => Cat)
.Left.JoinAlias(() => Cat.Languages, () => catLang)
.Fetch(x => x.Languages).Eager
.Where(() => catLang.IDLanguage == IDLanguage)
.Left.JoinAlias(() => Cat.SubCategories, () => subCat)
.Left.JoinAlias(() => subCat.Languages, () => subCatLang)
.Fetch(x => x.SubCategories).Eager
.Where(() => subCatLang.IDLanguage == IDLanguage)
.OrderBy(() => Cat.ID).Asc
.List<Category>();