I have an entitiy as
public class ClaimDetail
{
public virtual int Id { get; set; }
public virtual Claim Claim {get;set;}
public virtual string ServiceDateFrom { get; set; }
public virtual string DateCreated { get; set; }
public virtual ClaimDetail ParentClaimDetail { get; set; }
}
I want apply left outer join on on this table as
SELECT cd.ClaimDetailId ,
cd.ParentClaimDetail_id ,
cds.ClaimDetailId ,
cds.ParentClaimDetail_id ,
cds.DateCreated,
cd.DateCreated
FROM ClaimDetail AS cd left JOIN ClaimDetail AS cds ON
cd.ClaimDetailId = cds.ParentClaimDetail_id
I am implementing this query in nhibernate as
ICriteria query = session.CreateCriteria(typeof(ClaimDetail), "cd")
.CreateAlias("ParentClaimDetail", "cds", NHibernate.SqlCommand.JoinType.LeftOuterJoin);
query.SetProjection
(
Projections.ProjectionList()
.Add(Projections.Property("cd.ParentClaimDetail.Id"), "sks")
.Add(Projections.Property("cd.Id"),"cdid")
.Add(Projections.Property("cds.DateCreated"), "dc1")
.Add(Projections.Property("cd.DateCreated"), "dc2")
.Add(Projections.Property("cds.ParentClaimDetail.Id"), "cds")
.Add(Projections.Property("cds.Id"),"cdsid")
);
but this create criteria creating query as
SELECT cd.ClaimDetailId ,
cd.ParentClaimDetail_id ,
cds.ClaimDetailId ,
cds.ParentClaimDetail_id ,
cds.DateCreated,
cd.DateCreated
FROM ClaimDetail AS cd left JOIN ClaimDetail AS cds ON
cd.ParentClaimDetail_id = cds.ClaimDetailId
can any one help me.
Thanks in advance
It looks like you want to use a named query instead. The named query goes in the mapping XML and you can feed input into it. In addition, you can select a custom class to represent the entities of the resulting data.
Related
How do you do this query in NHibernate, with criteria or QueryOver?
select r.relationshipidentifier, r.publicrelationshipid
from relationship r
inner join (
select max(asofdate) as asofdate, s.relationshipidentifier
from relationship s
group by s.relationshipidentifier
) m
on r.asofdate = m.asofdate and r.relationshipidentifier = m.relationshipidentifier
Assume
public class Relationship {
public virtual Guid Id { get; set; }
public virtual DateTime AsOfDate { get; set; }
public virtual Guid RelationshipIdentifier { get; set; }
public virtual Guid PublicRelationshpId { get; set; }
}
the inner join can be described by a subquery.
something to the effect of -
QueryOver.Of<Relationship>()
.SelectList(list =>
list.SelectMax(r => r.AsOfDate),
list.GroupProperty(r=> r.RelationshipIdentifier)
)
and you can use the WithSubquery method of QueryOver to inner join to that subquery.
see this article for further details on QueryOver API.
I have the following classes:
public class Item
{
public int Id { get; set; }
public IDictionary<int, ItemLocal> { get; protected set; }
public ICollection<string> Tags { get; set; }
public int DefaultLanguageId { get; set; }
public DateTime Start { get; set; }
}
public class ItemLocal
{
public virtual Item Parent { get; set; }
public virtual int LanguageId { get; set; }
public string Title { get; set; }
public string Description { get; set; }
}
These map to the tables Item, ItemTag and ItemLocal. I want to make the following query via the criteria api:
select
i.Id,
i.Start,
l.Title
from
Item i
left join ItemLocal l on i.Id = l.ParentId and i.DefaultLangaugeId = l.LanguageId
order by
l.Title,
i.Id
But I dont know how to perform the left join with the nhibernate criteria api. Especially with the usage of the default language selection.
Any help is very appreciated.
I have found a solution:
Session
.CreateCriteria<Item>("i")
.CreateCriteria("Localization", "l", NHibernate.SqlCommand.JoinType.LeftOuterJoin)
.Add(Restrictions.Disjunction()
.Add(Restrictions.EqProperty("i.DefaultLanguageId", "l.LanguageId"))
.Add(Restrictions.IsNull("l.LanguageId"))
)
.AddOrder(Order.Asc("l.Title"))
.AddOrder(Order.Asc("w.Id"));
This seems to work but results in a query with a workaround WHERE clause. Would rather see that it could render a SQL query where the restrictions defined in the disjunction could be part of the OUTER LEFT JOIN ... ON ... statement.
I've been looking for a week after a correct synthax whithout success.
I have 2 classes :
public class ArtworkData
{
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
public virtual IList<CommentData> Comments { get; set; }
}
public class CommentData
{
public virtual Guid Id { get; set; }
public virtual string Text { get; set; }
public virtual ProfileData Profile { get; set; }
public virtual ArtworkData Artwork { get; set; }
public virtual DateTime Created { get; set; }
}
I want to do this query :
SELECT this_.ArtworkId as ArtworkId3_3_,
this_.Name as Name3_3_,
this_.Description as Descript3_3_3_,
FROM Artwork this_
LEFT outer JOIN
(SELECT c.ArtworkIdFk, count(1) Cnt
FROM Comment c
GROUP BY c.ArtworkIdFk) as com
on com.ArtworkIdFk = this_.ArtworkId
ORDER BY 1 desc
But I don't find the way to.
At this moment I just have something like this :
ICriteria c = this.Session.CreateCriteria(typeof(ArtworkData));
if(filter.Category !=null)
{
c.CreateAlias("Categories", "cat")
.Add(Restrictions.Eq("cat.Id", filter.Category.Id));
}
DetachedCriteria crit = DetachedCriteria.For(typeof(CommentData), "comment")
.SetProjection(Projections.ProjectionList()
.Add(Projections.Count("comment.Id").As("cnt"))
.Add(Projections.GroupProperty("comment.Artwork.Id")));
c.Add(Expression.Gt(Projections.SubQuery(crit), 0));
c.AddOrder(Order.Desc(Projections.SubQuery(crit)));
But it's not what I want.
I want to get all Artworks order by the number of comments (but I don't need to get this number).
Please help me! I'm going crazy!
I don't understand what are you trying to do with this weird SQL but if you need to get all Artworks with number of comments you can try this query:
<query name="ArtworkWithCommentsCount">
SELECT artwork.Name, artwork.Comments.size
FROM Artwork artwork
</query>
If you use NHibernate 3 you could use this code:
var artworks = Session.Query<Artwork>().OrderBy(a => Comments.Count);
Or you could use HQL:
Session.CreateQuery("from Artwork a order by size(a.Comments)")
Try Detached Criteria. Take a look at this blogpost.
I've got two tables. Invoice with columns CustomerID, InvoiceDate, Value, InvoiceTypeID (CustomerID and InvoiceDate make up a composite key) and InvoiceType with InvoiceTypeID and InvoiceTypeName columns.
I know I can create my objects like:
public class Invoice
{
public virtual int CustomerID { get; set; }
public virtual DateTime InvoiceDate { get; set; }
public virtual decimal Value { get; set; }
public virtual InvoiceType InvoiceType { get; set; }
}
public class InvoiceType
{
public virtual InvoiceTypeID { get; set; }
public virtual InvoiceTypeName { get; set; }
}
So the generated sql would look something like:
SELECT CustomerID, InvoiceDate, Value, InvoiceTypeID FROM Invoice WHERE CustomerID = x AND InvoiceDate = y
SELECT InvoiceTypeID, InvoiceTypeName FROM InvoiceType WHERE InvoiceTypeID = z
But rather that having two select queries executed to retrieve the data I would rather have one. I would also like to avoid using child object for simple lookup lists. So my object would look something like:
public class Invoice
{
public virtual int CustomerID { get; set; }
public virtual DateTime InvoiceDate { get; set; }
public virtual decimal Value { get; set; }
public virtual InvoiceTypeID { get; set; }
public virtual InvoiceTypeName { get; set; }
}
And my sql would look something like:
SELECT CustomerID, InvoiceDate, Value, InvoiceTypeID
FROM Invoice INNER JOIN InvoiceType ON Invoice.InvoiceTypeID = InvoiceType.InvoiceTypeID
WHERE CustomerID = x AND InvoiceDate = y
My question is how do I create the mapping for this?
I've tried using join but this tried to join using CustomerID and InvoiceDate, am I missing something obvious?
Thanks
If your goal is (as you said) to avoid two queries, you can retrieve the data using a single HQL statement:
select i, it from Invoice i fetch join i.type it where ...
...as documented in the hibernate docs. This should execute only one SQL select statement and retrieve everything without any mapping changes.
This is a regular HQL query and is executed as follows:
IQuery q = s.CreateQuery("select i, it from Invoice i fetch join i.type it where ...");
IList invoices = q.List();
More information is available on the hibernate query language page.
I've just delved into a bit of NHibernate and I'm having trouble with one of the more 'complex' (to me!) queries I have to write. The scenario is:
I've got a 'Staff' object which has a collection of 'Skills' attached. I'd like to pass in a list of 'Skills' to query against (e.g. if I only want people that can either 'Cook' or 'Code', or both) and return a list of matching Staff, but I'm having a little trouble....
What I've got object-wise is:
public class StaffMember : Resource
{
public virtual string EmployeeId { get; set; }
public virtual bool IsTeamLeader { get; set; }
public virtual StaffMember TeamLeader { get; set; }
public virtual IList<Skill> Skills { get; set; }
}
public class Skill : BaseDomainObject
{
public virtual string Name { get; set; }
}
And I guess the SQL would go something like:
select distinct st.*
from staff st, resource re
inner join staffskills sks on re.id = sks.staffresourceid
inner join skill ski on ski.id = sks.skillid
where st.resourceid = re.id
and ski.id in (1,2,3,4)
I tried to use "Expression.InG("Skills", skillsSearchList)" in the criteria, but that can't be used when two collections are in play (e.g. if they only had one skill, it would be fine!)... any pointers?
You need to
.CreateAlias("Skills", "sks")
.Add(Restrictions.In("sks.id", skillIdList))
I'm not sure if this can be done with a list of skill objects. Either way, the sql is going to end up the same as above.
Note that this will create a Cartesian product so you might want to use an exists subquery or .SetResultTransformer(new DistinctRootEntityResultTransformer()) to get back a list of distinct Staff.