nHibernate named queries
nHibernate named queries
Czasem wymagania biznesowe skłaniają programistów do tworzenia bardzo skomplikowanych powiązań między obiektami / zapytań.
Aby mieć je w jakimś 'przewidywalnym miejscu a nie rozrzucone po kodzie możemy użyć < query/> w mappingu.
Query jest niezależne od Class.
Mamy < sql-query />
Kolejnym fajnym elementem jest return któremu z łatwością możemy określić klasę której się spodziewamy jako wyniku.
Wywołanie jest równie łatwe jak poprzednio
Aby mieć je w jakimś 'przewidywalnym miejscu a nie rozrzucone po kodzie możemy użyć < query/> w mappingu.
Query jest niezależne od Class.
< ?xml version="1.0" ?> < hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" schema="dbo" > < class name="OH.BusinessObjects.Subject, BusinessObjects" table="Subject" where="IsDeleted = 0" dynamic-update="false" dynamic-insert="false" > < id name="ID" column="ID" type="long" unsaved-value="0"> < generator class="identity"/> < / id> < / class> < query name="qSubjectByName"> from Subject s where s.Name like :name < / query> < / hibernate-mapping>Wywołanie mogło by być w ten deseń:
IQuery query = Session.GetNamedQuery("qSubjectByName"); query.SetParameter("name","SomeName"); var list = query.List< Subject>();Ale co jeśli powiązania pomiędzy tabelami nie są tak oczywiste aby móc z nich skorzystać w nHibernate. Być może powiązania są tylko logiczne bez kluczy obcych. Lub nasze zapytanie jest na tyle skomplikowane że warto użyć SQLa aby go zoptymalizować.
Mamy < sql-query />
< ?xml version="1.0" ?> < hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" schema="dbo" > < class name="OH.BusinessObjects.Subject, BusinessObjects" table="Subject" where="IsDeleted = 0" dynamic-update="false" dynamic-insert="false" > < id name="ID" column="ID" type="long" unsaved-value="0"> < generator class="identity"/> < / id> < / class> < sql-query name="qMediumSubjecList"> < return alias="s" class="OH.BusinessObjects.Subject, BusinessObjects"/> < ![CDATA[ SELECT s.* FROM Subject s inner join SubjectAddress sa on sa.SubjectID = s.ID and s.IsCurrent=1 and s.IsDeleted = 0 and sa.IsDeleted =0 INNER JOIN Contact c ON sa.SelfInstanceGUID = c.SubjectAddressSelfInstanceGUID and c.IsDeleted=0 INNER JOIN Medium m on c.MediumID = m.ID and m.IsDeleted =0 WHERE m.ID = :mediumID ]]> < / sql-query> < / hibernate-mapping>Kluczowe jest [CDATA[ które zawiera dowolne zapytanie SQL.
Kolejnym fajnym elementem jest return któremu z łatwością możemy określić klasę której się spodziewamy jako wyniku.
Wywołanie jest równie łatwe jak poprzednio
IQuery query = Session.GetNamedQuery("qMediumSubjecList"); query.SetInt64("mediumID", MediumID); var list = query.List< Subject>();Możemy też zwrócić pojedyncze kolumny
< sql-query name="qSubjectLockingInfo"> < return-scalar column="LastChangeDate" type="datetime"/> < return-scalar column="LockedSessionID" type="Guid"/> < ![CDATA[ SELECT m.LastChangeDate AS LastChangeDate , m.LockedSessionID AS LockedSessionID FROM Subject m WHERE m.ID = :subjectID ]]> < / sql-query>A jeśli będziemy posiadać klasę z odpowiednimi dwoma propercjami - możemy przetransformować wynik na klasę i transformer.
public class LockingInfo { public virtual DateTime LastChangeDate { get; set; } public virtual Guid? LockedSessionID { get; set; } } public class LockingInfoResultTransformer : IResultTransformer { #region IResultTransformer Members public IList TransformList(IList collection) { return collection == null ? null : collection.OfType< LockingInfo>().ToList(); } public object TransformTuple(object[] tuple, string[] aliases) { if (tuple == null || tuple.Length == 0 || aliases == null || aliases.Length == 0) { return null; } LockingInfo ret = new LockingInfo(); for (int i = 0; i < aliases.Length; i++ ) { switch (aliases[i]) { case "LastChangeDate": ret.LastChangeDate = (DateTime)tuple[i]; break; case "LockedSessionID": ret.LockedSessionID = (Guid?)tuple[i]; break; } } return ret; } #endregion }
Query query = session.GetNamedQuery("qSubjectLockingInfo"); query.SetInt64("subjectID", ID); query.SetResultTransformer(new LockingInfoResultTransformer()); LockingInfo lockInfo = query.UniqueResult< LockingInfo>();Na koniec link do dokumentacji tutaj. i słowo o LinqToSQL tuta znajdziemy wpis o nazwanych query w LinqToSQL wydaje się jednak że można to porównać do < query> z nHibbernata, natomiast nie udało mi się znaleźć odpowiednika < sql-query>.
Komentarze
Prześlij komentarz