Nhibernate QueryOver: Count in where clause - nhibernate

Any tips on how to convert the following to QueryOver:
var widget = session.Query<Widget>()
.Fetch(x => x.NotificationJobs)
.Where(x =>
x.Status == Status.Active &&
!x.NotificationJobs.Any())
.OrderByDescending(x => x.DateCreated)
.Take(1)
.SingleOrDefault();
Want to get a widget that has no notification jobs.

var widgetWithNoNotificationJob = session.QueryOver<Widget>()
.Where( x => x.Status == Status.Active )
.OrderBy( x => x.DateCreated ).Desc
.Left.JoinQueryOver<NotificationJob>( x => x.NotificationJobs )
.Where( x => x.NotificationJobId == null )
.Take( 1 )
.SingleOrDefault();
This will produce SQL with a LEFT OUTER JOIN on the NotificationJob table and a WHERE clause with NotificationJob.NotificationJobId IS NULL.
Hopefully this will point you in the right direction.

Related

The ExceptResultOperator result operator is not current supported

I want to exclude one resultset from another and I am using Except for that but it is giving error that "The ExceptResultOperator result operator is not current supported". I can not use all the conditions in where clause of a single query as it will give me unexcepted result.
//Sample code what I have tried
var result1 = Session.Query<Table>()
.Where(x => x.ColumnName != null && !x.active)
.Select(x => x)
var result2 = Session.Query<Table>()
.Where(x => x.Active)
.Except(result1)
.Select(x => x)
You can use Contains instead of Except:
var result1 = Session.Query<Table>()
.Where(x => x.ColumnName != null && !x.active)
.Select(x => x)
var result2 = Session.Query<Table>()
.Where(x => x.Active && !result1.Contains(x))
.Select(x => x)

How to Convert Sql to Linq with Distinct(id)

select count(distinct LicencePlate) from MT_Vehicle where IsDeleted=0 and CreatedBy = 1
var count = MT_Vehicle.Where(x => x.IsDeleted==0 && x.CreatedBy == 1)
.Select(x => x.LicencePlate)
.Distinct()
.Count();
You can write that as:
var count = db.MT_Vehicle
.Where( v => v.IsDeleted == 0 && v.CreatedBy == 1 )
.Select(v => v.LicencePlate)
.Distinct()
.Count();

fluent hibernate Transformers.AliasToBean is not working as expected

I have three tables. One is the master table: TableA. One table is referenced by TableA called ReferencedTable and lastly a lookup table referenced by ReferencedTable.
I have this query that returns the ten most recent objects as:
TableADTO TableAlias = null;
LookupTableDTO LookupTableAlias = null;
ReferencedDTO ReferencedAlias = null;
dtos = session.QueryOver(() => TableAlias)
.JoinAlias(() => TableAlias.Object, () =>ReferencedAlias)
.JoinAlias(() => ReferencedAlias.ObjectType, () => LookupTableAlias)
.Where(() => ReferencedAlias.PersonId == user.Id &&
(LookupTableAlias.Id != INVOICE_ID ||
LookupTableAlias.Id != FINANCIAL_ID) &&
TableAlias.Status == NEW_STATUS_FLAG &&
ReferencedAlias.ReceivedDate < DateTime.Now)
.Take(10)
.List()
.Select(dto=>
new AbreviatedDTO
{
Id = dto.Referenced.Id,
Field1 = dto.Field1,
Priority = dto.Referenced.Priority,
ReceivedDate = dto.Referenced.ReceivedDate,
Field1 = dto.Referenced.Field1,
Type = dto.Referenced.Lookup.TypeCode,
Status = dto.Status
}).ToList();
This works as expected. However, I thought the the transformation below would work too. It does bring 10 objects but the objects have all default values and are not populated (e.g. AbreviatedDTO.ReceivedDate = DateTime.Minimum). Am I doing something wrong with the QueryOver?
Any help would be appreciated.
Bill N
TableDTO TableAlias = null;
LookupTableDTO LookupTableAlias = null;
ReferencedDTO ReferencedAlias = null;
dtos = session.QueryOver(() => TableAlias)
.JoinAlias(() => TableAlias.Object, () =>ReferencedAlias)
.JoinAlias(() => ReferencedAlias.ObjectType, () => LookupTableAlias)
.Where(() => ReferencedAlias.PersonId == user.Id &&
(LookupTableAlias.Id != INVOICE_ID ||
LookupTableAlias.Id != FINANCIAL_ID) &&
TableAlias.Status == NEW_STATUS_FLAG &&
ReferencedAlias.ReceivedDate < DateTime.Now)
.SelectList(list => list
.Select(x => TableAlias.Field1)
.Select(x => ReferencedAlias.Id)
.Select(x => ReferencedAlias.Field1)
.Select(x => ReferencedAlias.ReceivedDate)
.Select(x => ReferencedAlias.Priority)
.Select(x => LookupTableAlias.TypeCode))
.TransformUsing(Transformers.AliasToBean<AbreviatedDTO>())
.Take(10)
.List<AbreviatedDTO>()
you'll need to define an alias for each selected field same as the propertyname in the resulting dto
AbreviatedDTO alias = null;
// in query
.SelectList(list => list
.Select(() => TableAlias.Field1).WithAlias(() => alias.Field1)

Construct NHibernate query that orders by a boolean condition

I have two entities: Client, and AccountPlan, that have a 1 to 0..1 relationship. I would like to fetch my Clients, ordered first by Clients that have an AccountPlan, and then by Clients that do not. When I try the following Linq to Nhibernate query:
return NHibernateSession.Current.Query<Client>()
.Where(x => x.SalesRepId == id)
.OrderBy(x => x.AccountPlan == null);
I get a QuerySyntaxException with the following message:
{"Exception of type 'Antlr.Runtime.NoViableAltException' was thrown.
[.OrderBy(.Where(NHibernate.Linq.NhQueryable`1[FIS.AccountManagement.Core.Domain.Client],
Quote((x, ) => (Equal(x.SalesRepId, p1))), ), Quote((x, ) =>
(Equal(x.AccountPlan, ))), )]"}
Here's the mapping relationship between the two entities, if that's important:
public ClientMap()
{
HasOne(x => x.AccountPlan).PropertyRef(r => r.Client);
}
public AccountPlanMap()
{
DynamicInsert();
References(x => x.Client, "EntityID");
}
Does anyone know of a query from one of NHibernate's myriad APIs that will accomplish what I want? Thanks in advance.
two queries in one roundtrip concated together
var clientsWithPlan = NHibernateSession.Current.Query<Client>()
.Where(x => x.SalesRepId == id)
.Where(x => x.AccountPlan != null)
.Future();
var clientsWithoutPlan = NHibernateSession.Current.Query<Client>()
.Where(x => x.SalesRepId == id)
.Where(x => x.AccountPlan == null)
.Future();
return clientsWithPlan.Concat(clientsWithoutPlan);
Using a conditional operator:
return NHibernateSession.Current.Query<Client>()
.Where(x => x.SalesRepId == id)
.OrderBy(x => x.AccountPlan == null ? 1 : 0);
As a workaround, you could retrieve all Clients from the database unordered, then perform the ordering in the application using LINQ to objects:
var clients = NHibernateSession.Current.QueryOver<Client>()
.Where(x => x.SalesRepId == id)
.Fetch(x => x.Account).Eager
.List();
return clients.OrderBy(x => x.AccountPlan == null);

NHibernate QueryOver association does not contain item

could someone help me to translate LINQ expression to Nhibernate QueryOver
from m in messages
where !m.Recipients.Any(rcpt => rcpt.IsDeleted && rcpt.User = user)
I tried this
var qry = Session.QueryOver<UserMessage>();
qry.Where(m => m.Recipients.Any(r => !r.IsDeleted && r.User == user));
but got
System.Exception : Unrecognised method call: System.Linq.Enumerable:Boolean Any[TSource](System.Collections.Generic.IEnumerable1[TSource], System.Func2[TSource,System.Boolean]
!m.Recipients.Any(...) translates to a "not exists" sub-query. You will need a couple of aliases to correlate the sub-query with the main query, and the sub-query will need to have a projection to make NHibernate happy.
Try something like this:
UserMessage messageAlias = null;
UserMessage recipientMessageAlias = null;
var subquery = QueryOver.Of<MessageRecipient>()
.JoinAlias(x => x.Message, () => recipientMessageAlias)
.Where(x => x.IsDeleted == true) // your criteria
.Where(x => x.User.Id == userId)
.Where(() => recipientMessageAlias.Id == messageAlias.Id) // correlated subquery
.Select(x => x.Id); // projection
var query = session.QueryOver(() => messageAlias)
.Where(Subqueries.WhereNotExists(subquery));
return query.List();
I managed to it this way:
UserMessage messageAlias = null;
var qry = Session.QueryOver<UserMessage>(() => messageAlias);
UserMessageRecipient recipientAlias = null;
var deletedbyUser = QueryOver.Of(() => recipientAlias)
.Select(x => x.Id)
.Where( () => recipientAlias.Message.Id == messageAlias.Id
&& (recipientAlias.Recipient == query.User && recipientAlias.IsDeleted))
.DetachedCriteria;
qry.Where(Subqueries.NotExists(deletedbyUser));
Try to use the Linq version with session.Query<> instead of QueryOver
var qry = Session.Query<UserMessage>();
qry.Where(m => m.Recipients.Any(r => !r.IsDeleted && r.User == user));