EmployeePayHistory payHistory = null; var persons = session.QueryOver<Person>() .Left.JoinAlias(p => p.PayHistories, () => payHistory) .Where( Restrictions.Eq( Projections.Count(() => payHistory.EmployeePayHistoryCompositePK.BusinessEntityId) , 0 ) ) .SelectList(x => x .SelectGroup(p => p.BusinessEntityId) .SelectGroup(p => p.FirstName) .SelectGroup(p => p.LastName) .SelectCount(p => payHistory.EmployeePayHistoryCompositePK.BusinessEntityId) ) .List<object[]>() .Select(cols => new { Id = (int)cols[0], FirstName = (string)cols[1], LastName = (string)cols[2], Count = (int)cols[3] }); persons.ToList();
Generated SQL:
SELECT this_.BusinessEntityId as y0_, this_.FirstName as y1_, this_.LastName as y2_, count(payhistory1_.BusinessEntityId) as y3_ FROM Person.Person this_ left outer join HumanResources.EmployeePayHistory payhistory1_ on this_.BusinessEntityId=payhistory1_.BusinessEntityId GROUP BY this_.BusinessEntityId, this_.FirstName, this_.LastName HAVING count(payhistory1_.BusinessEntityId) = @p0; @p0 = 0 [Type: Int32 (0)]
One-stop shop code, complete working code. Just install AdventureWorks2008R2 database:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using NHibernate.Cfg; using NHibernate.Cfg.MappingSchema; using NHibernate.Criterion; using NHibernate.Mapping.ByCode.Conformist; using NHibernate.Linq; namespace Craft { class Program { static void Main(string[] args) { using (var session = Mapper.SessionFactory.OpenSession()) { EmployeePayHistory payHistory = null; var persons = session.QueryOver<Person>() .Left.JoinAlias(p => p.PayHistories, () => payHistory) .Where( Restrictions.Eq( Projections.Count(() => payHistory.EmployeePayHistoryCompositePK.BusinessEntityId) , 0 ) ) .SelectList(x => x .SelectGroup(p => p.BusinessEntityId) .SelectGroup(p => p.FirstName) .SelectGroup(p => p.LastName) .SelectCount(p => payHistory.EmployeePayHistoryCompositePK.BusinessEntityId) ) .List<object[]>() .Select(cols => new { Id = (int)cols[0], FirstName = (string)cols[1], LastName = (string)cols[2], Count = (int)cols[3] }); persons.ToList(); Console.ReadLine(); } // using } // Main } //class Program public static class Mapper { static NHibernate.ISessionFactory _sessionFactory = Mapper.GetSessionFactory(); public static NHibernate.ISessionFactory SessionFactory { get { return _sessionFactory; } } static NHibernate.ISessionFactory GetSessionFactory() { var mapper = new NHibernate.Mapping.ByCode.ModelMapper(); mapper.AddMappings( new[] { typeof(PersonMapping) , typeof(EmployeePayHistoryMapping) }); var cfg = new NHibernate.Cfg.Configuration(); cfg.DataBaseIntegration(c => { c.Driver<NHibernate.Driver.Sql2008ClientDriver>(); c.Dialect<NHibernate.Dialect.MsSql2008Dialect>(); c.ConnectionString = "Server=.;Database=AdventureWorks2008R2;Trusted_Connection=True;"; c.LogFormattedSql = true; c.LogSqlInConsole = true; }); HbmMapping domainMapping = mapper.CompileMappingForAllExplicitlyAddedEntities(); cfg.AddMapping(domainMapping); var sf = cfg.BuildSessionFactory(); return sf; } } public class PersonMapping : ClassMapping<Person> { public PersonMapping() { Table("Person.Person"); Id(x => x.BusinessEntityId); Property(x => x.FirstName); Property(x => x.LastName); Bag(list => list.PayHistories, rel => rel.Key(k => k.Column("BusinessEntityId")), relType => relType.OneToMany()); } } public class EmployeePayHistoryMapping : ClassMapping<EmployeePayHistory> { public EmployeePayHistoryMapping() { Table("HumanResources.EmployeePayHistory"); ComponentAsId(x => x.EmployeePayHistoryCompositePK, x => { x.Property(y => y.BusinessEntityId); x.Property(y => y.RateChangeDate); }); ManyToOne(x => x.Person, k => { k.Column("BusinessEntityId"); k.Insert(false); k.Update(false); }); Property(x => x.Rate); } } public class Person { public virtual int BusinessEntityId { get; set; } public virtual string FirstName { get; set; } public virtual string LastName { get; set; } public virtual IList<EmployeePayHistory> PayHistories { get; set; } } public class EmployeePayHistory { EmployeePayHistoryCompositePK _pk = new EmployeePayHistoryCompositePK(); public virtual EmployeePayHistoryCompositePK EmployeePayHistoryCompositePK { get { return _pk; } set { _pk = value; } } Person _person; public virtual Person Person { get { return _person; } set { _person = value; _pk.BusinessEntityId = _person.BusinessEntityId; } } public virtual decimal Rate { get; set; } } // AdventureWorks is fond of composite primary key. Composite unique is better public class EmployeePayHistoryCompositePK { public virtual int BusinessEntityId { get; set; } public virtual DateTime RateChangeDate { get; set; } public override bool Equals(object obj) { if (obj == null) return false; var t = obj as EmployeePayHistoryCompositePK; if (t == null) return false; if (BusinessEntityId == t.BusinessEntityId && RateChangeDate == t.RateChangeDate) return true; return false; } public override int GetHashCode() { return (BusinessEntityId + "|" + RateChangeDate).GetHashCode(); } } }
Happy Coding! ツ
Related: http://www.ienablemuch.com/2014/07/orm-expectations.html
No comments:
Post a Comment