Below are my entities. One ContractBill can have multiple SubscriberInvoices.
public class ContractBill
{
public virtual Int32 ContractID { get; set; }
public virtual Int32 CustomerID { get; set; }
public virtual string ContractStatus { get; set; }
public virtual Customer Customer { get; set; }
public virtual IList<SubscriberInvoice> InvoiceList { get; set; }
public ContractBill() { }
}
public class ContractBillMap : ClassMap<ContractBill>
{
public ContractBillMap()
{
Table("GT_CONTRACT");
Id(x => x.ContractID, "GF_CONT_ID").GeneratedBy.Increment();
Map(x => x.CustomerID, "GF_CUST_ID");
Map(x => x.ContractStatus, "GF_CONTRACT_STATUS");
HasMany(x => x.InvoiceList).KeyColumn("GF_CONT_ID").Not.LazyLoad();
}
}
public class SubscriberInvoice : Object
{
virtual public String InvoiceID { get; set; }
virtual public Int32 ContractID { get; set; }
virtual public Int32 CustomerID { get; set; }
virtual public String BillPeriod { get; set; }
virtual public Double Amount { get; set; }
virtual public Double MinimumAmount { get; set; }
virtual public DateTime PayByDate { get; set; }
virtual public String IsPaid { get; set; }
virtual public Double AmountPaid { get; set; }
public SubscriberInvoice()
{
}
}
public class SubscriberInvoiceMap : ClassMap<SubscriberInvoice>
{
public SubscriberInvoiceMap()
{
Table("GT_BILL");
CompositeId()
.KeyProperty(x => x.InvoiceID, "GF_BILL_ID")
.KeyProperty(x => x.ContractID, "GF_CONT_ID")
.KeyProperty(x => x.BillPeriod, "GF_BILL_PERIOD")
Map(x => x.Amount, "GF_AMOUNT");
Map(x => x.MinimumAmount, "GF_MINIMUM_AMOUNT");
Map(x => x.PayByDate, "GF_PAY_BY_DATE");
Map(x => x.IsPaid, "GF_PAID");
Map(x => x.AmountPaid, "GF_AMOUNT_PAID");
}
}
//Get distinct BillContract having more than two non-paid Subscriber Invoices.
ICriteria criteria = session.CreateCriteria(typeof(ContractBill), "cb1");
string aliasName = "invoice";
string prefix = aliasName + ".";
criteria = criteria.CreateAlias("InvoiceList", aliasName);
criteria = criteria.Add(Expression.Eq(prefix + "IsPaid", "N"));
// below detached query will give the count of non paid invoice list
DetachedCriteria crit = DetachedCriteria.For(typeof(ContractBill))
.CreateAlias("InvoiceList", "InvoiceList")
.SetProjection(Projections.ProjectionList()
.Add(Projections.RowCount()))
.Add(Property.ForName("ContractID").EqProperty("cb1.ContractID"));
//Non paid invoice Count = 2
criteria = criteria.Add(Restrictions.Gt(Projections.SubQuery(crit), 2));
//Not giving proper reasult when being used with paging
//criteria = Criteria.SetResultTransformer(Transformers.DistinctRootEntity);
criteria =criteria.SetFirstResult(0).SetMaxResults(10);
//Tried with below detached query, but not getting distinct record
DetachedCriteria crit1 = DetachedCriteria.For(typeof(ContractBill))
.Add(Restrictions.EqProperty ("ContractID", "cb1.ContractID"))
.CreateCriteria("InvoiceList")
.SetProjection(Projections.Distinct(Projections.Id()));
criteria = criteria.Add(Subqueries.PropertyIn("cb1.ContractID", crit1));
IList<ContractBill> matchingObjects = criteria.List<ContractBill>();
Above code is not giving distinct result. Please suggest how to get the distinct ContractBill records.
For displaying records with paging, I need to get the total record count for above criteria also.
Related
I want to use automapper to flatten a list of entity heirarchies returned back from Entity Framework Core.
Here are my entities:
public class Employee {
public int Id { get; set; }
[Required]
public string Name { get; set; }
public double? PayRateRegular { get; set; }
public double? PayRateLoadedRegular { get; set; }
public double? GMOutput { get; set; }
public string EmployeeType { get; set; }
//List of CommissionDetails where this employee is the consultant
public IEnumerable<CommissionDetail> CommissionDetailConsultants { get; set; } = new List<CommissionDetail>();
}
public class Project {
public int Id { get; set; }
public string Description { get; set; }
public double? BillRateRegular { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
public Customer Customer { get; set; }
public int CustomerId { get; set; }
}
public class Customer {
public int Id { get; set; }
public string Name { get; set; }
}
public class CommissionDetail {
public string SaleType { get; set; }
public double CommissionPercent { get; set; }
public bool? IsReported { get; set; }
public int? Level { get; set; }
public string BasedOn { get; set; }
public Project Project { get; set; }
public int ProjectId { get; set; }
public Employee SalesPerson { get; set; }
public int SalesPersonEmployeeId { get; set; }
public Employee Consultant { get; set; }
public int ConsultantEmployeeId { get; set; }
}
Here is my DTO:
public class ConsultantGridViewModel
{
public string ConsultantName { get; set; }
public string CustomerName { get; set; }
public string SalesPersonName { get; set; }
public string ProjectDescription { get; set; }
public double? PayRate { get; set; }
public double? LoadedRated { get; set; }
public double? BillRate { get; set; }
public double? GM { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
public double CommissionPercent { get; set; }
public int? CommissionLevel { get; set; }
}
Here is my call to EF:
return await _dbContext.Employee
.AsNoTracking()
.Include(e => e.CommissionDetailConsultants)
.ThenInclude(cd => cd.SalesPerson)
.Include(e => e.CommissionDetailConsultants)
.ThenInclude(cd => cd.Project)
.ThenInclude(p => p.Customer)
.Where(e => e.EmployeeType == "Contractor")
.ToListAsync();
I'm currently flattening it with SelectMany as follows:
var consultants = employees.SelectMany(e =>
e.CommissionDetailConsultants,
(emp, com) => new ConsultantGridViewModel {
ConsultantName = emp.Name,
PayRate = emp.PayRateRegular,
LoadedRated = emp.PayRateLoadedRegular,
GM = emp.GMOutput,
BillRate = com.Project.BillRateRegular,
ProjectDescription = com.Project.Description,
ProjectStartDate = com.Project.StartDate,
ProjectEndDate = com.Project.EndDate,
CustomerName = com.Project.Customer.Name,
SalesPersonName = com.SalesPerson.Name,
CommissionPercent = com.CommissionPercent,
CommissionLevel = com.Level
});
I would like to use automapper instead. I've used automapper for all my other DTO mappings but I can't figure out how to use it to flatten a nested object like this.
Let rewrite what you have currently with SelectMany + Select utilizing the Consultant navigation property:
var consultants = employees
.SelectMany(e => e.CommissionDetailConsultants)
.Select(com => new ConsultantGridViewModel
{
ConsultantName = com.Consultant.Name,
PayRate = com.Consultant.PayRateRegular,
LoadedRated = com.Consultant.PayRateLoadedRegular,
GM = com.Consultant.GMOutput,
BillRate = com.Project.BillRateRegular,
ProjectDescription = com.Project.Description,
ProjectStartDate = com.Project.StartDate,
ProjectEndDate = com.Project.EndDate,
CustomerName = com.Project.Customer.Name,
SalesPersonName = com.SalesPerson.Name,
CommissionPercent = com.CommissionPercent,
CommissionLevel = com.Level
});
Now it can be seen that the CommissionDetail contains all the necessary data, so while you can't avoid SelectMany, you can replace the Select by creating a mapping from CommissionDetail to ConsultantGridViewModel and use something like this:
var consultants = Mapper.Map<List<ConsultantGridViewModel>>(
employees.SelectMany(e => e.CommissionDetailConsultants));
or even better, project directly to the DTO:
var consultants = await _dbContext.Employee
.Where(e => e.EmployeeType == "Contractor")
.SelectMany(e => e.CommissionDetailConsultants)
.ProjectTo<ConsultantGridViewModel>()
.ToListAsync();
Now the mapping.
AutoMapper will map automatically members like CommisionPercent. Also the Flattening feature will handle automatically mappings like Project.EndDate -> ProjectEndDate, Consultant.Name -> ConsultantName etc.
So as usual with AutoMapper you should specify manually the mapping of properties which don't fall into previous categories. The minimal configuration in this case would be something like this:
Mapper.Initialize(cfg =>
{
cfg.CreateMap<CommissionDetail, ConsultantGridViewModel>()
.ForMember(dst => dst.PayRate, opt => opt.MapFrom(src => src.Consultant.PayRateRegular))
.ForMember(dst => dst.LoadedRated, opt => opt.MapFrom(src => src.Consultant.PayRateLoadedRegular))
.ForMember(dst => dst.GM, opt => opt.MapFrom(src => src.Consultant.GMOutput))
.ForMember(dst => dst.BillRate, opt => opt.MapFrom(src => src.Project.BillRateRegular))
.ForMember(dst => dst.CustomerName, opt => opt.MapFrom(src => src.Project.Customer.Name))
.ForMember(dst => dst.CommissionLevel, opt => opt.MapFrom(src => src.Level));
});
P.S. You can even avoid SelectMany by basing your queries directly on CommissionDetail entity, for instance
var consultants = await _dbContext.Set<CommissionDetail>()
.Where(c => c.Consultant.EmployeeType == "Contractor")
.ProjectTo<ConsultantGridViewModel>()
.ToListAsync();
Note that when you do direct projection, there is no need of AsNoTracking or Include / ThenInclude.
I was wondering if someone could help me. I want to perform SQL INNER JOIN operation by using NHibernate. First of all let me introduce you to the structure of my database.
I have the following parameters into my C# method: int documentId, int userId, int folderId. My main goal is to get RoleDocumentValueEntity. By using USER_ID and FOLDER_ID I can get the unique FolderUserRoleEntity. I am looking for the ROLE_ID. I want to join ROLE_DOCUMENT_VALUE and FOLDER_USER_ROLES tables by ROLE_ID where DOCUMENT_ID is equal to specific value which I have as a parameter of C# method.
My entities:
public class RoleDocumentValueEntity
{
public virtual int Id { get; set; }
public virtual RoleEntity Role { get; set; }
public virtual DocumentEntity Document { get; set; }
public virtual string Text { get; set; }
}
public class RoleEntity
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual IList<UserRoleEntity> UserRoles { get; set; }
public virtual IList<FolderUserRoleEntity> FolderUserRoles { get; set; }
}
public class FolderEntity
{
public virtual int Id { get; set; }
public virtual UserEntity User { get; set; }
public virtual IList<DocumentEntity> Documents {get; set;}
}
public class UserEntity
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
}
public class UserRoleEntity
{
public virtual int Id { get; set; }
public virtual int UserId { get; set; }
public virtual RoleEntity Role { get; set; }
}
public class FolderUserRoleEntity
{
public virtual int Id { get; set; }
public virtual int UserId { get; set; }
public virtual RoleEntity Role { get; set; }
public virtual FolderEntity Folder { get; set; }
}
Mappings:
public class RoleDocumentValueMap : BaseDatabaseMap<RoleDocumentValueEntity>
{
public RoleDocumentValueMap()
{
this.Table("ROLE_DOCUMENT_VALUE");
Id(x => x.Id, "ROLE_DOCUMENT_VALUE_ID");
// Relationships
References(x => x.Role)
.Column("ROLE_ID")
.Cascade.None();
References(x => x.Document)
.Column("DOCUMENT_ID")
.Cascade.None();
}
}
public class RoleMap : BaseDatabaseMap<RoleEntity>
{
public RoleMap()
{
this.Table("ROLES");
Id(x => x.Id, "ROLE_ID");
HasMany(x => x.UserRoles)
.KeyColumn("ROLE_ID")
.Cascade.All()
.Inverse();
HasMany(x => x.FolderUserRoles)
.KeyColumn("ROLE_ID")
.Cascade.All()
.Inverse();
}
}
public class UserRoleMap : BaseDatabaseMap<UserRoleEntity>
{
public UserRoleMap()
{
this.Table("USER_ROLES");
this.Id(x => x.Id, "USER_ROLE_ID");
Map(x => x.UserId).Column("USER_ID");
References(x => x.Role).Column("ROLE_ID").Cascade.None().Fetch.Join();
}
}
public class FolderUserRoleMap : BaseDatabaseMap<FolderUserRoleEntity>
{
public FolderUserRoleMap()
{
this.Table("FOLDER_USER_ROLES");
Id(x => x.Id, "FOLDER_USER_ROLE_ID");
Map(x => x.UserId).Column("USER_ID");
References(x => x.Folder).Column("FOLDER_ID").Cascade.None().Fetch.Join();
References(x => x.Role).Column("ROLE_ID").Cascade.None().Fetch.Join().Not.LazyLoad();
}
}
public class FolderMap : BaseDatabaseMap<FolderEntity>
{
public FolderMap()
{
this.Table("FOLDERS");
Id(x => x.Id, "FOLDER_ID");
HasMany(x => x.Documents)
.Cascade
.AllDeleteOrphan()
.Inverse()
.KeyColumn("FOLDER_ID");
}
}
public class DocumentMap : BaseDatabaseMap<DocumentEntity>
{
public DocumentMap()
{
this.Table("DOCUMENTS");
Id(x => x.Id, "DOCUMENT_ID");
// Relationships
References(x => x.Folder)
.Column("FOLDER_ID")
.Cascade.None();
}
}
INNER JOIN
I manually created SQL query which I want to get by using NHibernate.
SELECT ROLE_DOCUMENT_VALUE.*
FROM ROLE_DOCUMENT_VALUE
INNER JOIN FOLDER_USER_ROLES ON FOLDER_USER_ROLES.ROLE_ID = ROLE_DOCUMENT_VALUE.ROLE_ID
AND FOLDER_USER_ROLES.FOLDER_ID = ?
AND FOLDER_USER_ROLES.USER_ID = ?
AND ROLE_DOCUMENT_VALUE.DOCUMENT_ID = ?;
It looks like my NHibernate criteria should look like this one:
var result = this.Session.CreateCriteria<RoleDocumentValueEntity>()
.CreateCriteria("FolderUserRoles", "fr")
.Add(Restrictions.Eq("fr.UserId", userId))
// etc
.List();
But this criteria cannot be performed because RoleDocumentValueEntity doesn't have such property as FolderUserRoles.
Please, could you provide me what is the best practice in this case? How can I create the SQL query which I want by using NHibernate?
you could use linq support for Nhibernate to achieve this easily,
from doc in Session.Query<RoleDocumentValueEntity>()
join role in Session.Query<FolderUserRoleEntity>()
on doc.Role equals role.Role
i am new to fluent nhibernate. i'm developing a project contains following 3 tables in its database:
"Person",
"RealPerson" and
"LegalPerson"
these three tables have relation as shown in picture:
all entities in my code such as these three entities are inherited from a base entity class here is the code of these entities
public class Person : Entity
{
public virtual RealPerson RealPerson { set; get; }
public virtual LegalPerson LegalPerson { set; get; }
}
public class RealPerson : Entity
{
public virtual string FirstName { set; get; }
public virtual string LastName { set; get; }
public virtual string FatherName { set; get; }
public virtual string NationalCode { set; get; }
public virtual DateTime BirthDate { set; get; }
public virtual string PhoneNumber { set; get; }
public virtual string MobileNumber { set; get; }
public virtual string EmailAddress { set; get; }
public virtual string HomeAddress { set; get; }
public virtual string WorkAddress { set; get; }
public virtual RealPerson Proxy { set; get; }
}
public class LegalPerson : Entity
{
public virtual string LegalPerson_Name { set; get; }
public virtual string RegistrationNumber { set; get; }
public virtual string Address { set; get; }
public virtual string PhoneNumber1 { set; get; }
public virtual string PhoneNumber2 { set; get; }
public virtual string PhoneNumber3 { set; get; }
public virtual RealPerson Proxy { set; get; }
}
and the code of base entity class is here:
public class Entity
{
protected bool Equals(Entity other)
{
if (other == null)
return false;
if (Id == Guid.Empty || other.Id == Guid.Empty)
return base.Equals(other);
return Id.Equals(other.Id);
}
public virtual Guid Id { set; get; }
public override int GetHashCode()
{
return Id.GetHashCode();
}
public override bool Equals(object obj)
{
if (obj is Entity)
return Equals((Entity)obj);
return base.Equals(obj);
}
protected ISession Session
{
get { return SessionAccountant.GetSession(); }
}
public virtual void Save()
{
Session.SaveOrUpdate(this);
}
public virtual void Delete()
{
Session.Delete(this);
}
}
Finally the classmaps are as following:
public class PersonMapping : ClassMap<Person>
{
public PersonMapping()
{
Table("Person");
Id(x => x.Id).GeneratedBy.GuidComb().Column("Person_Id");
References(x => x.RealPerson).Nullable().LazyLoad().Column("RealPerson_Id");
References(x => x.LegalPerson).Nullable().LazyLoad().Column("LegalPerson_Id");
}
}
public class RealPersonMapping : ClassMap<RealPerson>
{
public RealPersonMapping()
{
Table("RealPerson");
Id(x => x.Id).GeneratedBy.GuidComb().Column("RealPerson_Id");
Map(x => x.FirstName).Not.Nullable().Column("FirstName");
Map(x => x.LastName).Not.Nullable().Column("LastName");
Map(x => x.FatherName).Not.Nullable().Column("FatherName");
Map(x => x.NationalCode).Not.Nullable().Column("NationalCode");
Map(x => x.BirthDate).Nullable().Column("BirthDate");
Map(x => x.ShenasnamehNumber).Nullable().Column("ShenasnamehNumber");
Map(x => x.PhoneNumber).Nullable().Column("PhoneNumber");
Map(x => x.MobileNumber).Nullable().Column("MobileNumber");
Map(x => x.EmailAddress).Nullable().Column("EmailAddress");
Map(x => x.HomeAddress).Nullable().Column("HomeAddress");
Map(x => x.WorkAddress).Nullable().Column("WorkAddress");
References(x => x.Proxy).Nullable().LazyLoad().Column("Proxy_Id");
}
}
public class LegalPersonMapping : ClassMap<LegalPerson>
{
public LegalPersonMapping()
{
Table("LegalPerson");
Id(x => x.Id).GeneratedBy.GuidComb().Column("LegalPerson_Id");
Map(x => x.LegalPerson_Name).Not.Nullable().Column("LegalPerson_Name");
Map(x => x.RegistrationNumber).Not.Nullable().Column("RegistrationNumber");
Map(x => x.Address).Not.Nullable().Column("Address");
Map(x => x.PhoneNumber1).Nullable().Column("PhoneNumber1");
Map(x => x.PhoneNumber2).Nullable().Column("PhoneNumber2");
Map(x => x.PhoneNumber3).Nullable().Column("PhoneNumber3");
References(x => x.Proxy).Nullable().LazyLoad().Column("Proxy_Id");
}
}
i set the configuration and create a session. but when i run the project i get this exception at run time:
An unhandled exception of type 'NHibernate.MappingException' occurred in NHibernate.dll
Additional information: Could not determine type for: EntitiesClasses.Person
what is wrong with this code?!
You need to inherit from SubclassMap.
See here http://notherdev.blogspot.com/2012/01/mapping-by-code-inheritance.html?m=1
I think this is going to change your schema in that your base class isn't going to have the id of the subclass. The id of the base class is the id of the subclass.
I have a need to create a TreeMenu using NHibernate.
Here is what i cameup with:
public class CategoryMap : ClassMap<Category>
{
public CategoryMap()
{
Id(x => x.Id);
Map(x => x.AppId);
Map(x => x.Title);
Map(x => x.MaxDepth).Default("3");
Map(x => x.IsActive);
References(x => x.Parent).LazyLoad().Column("ParentId");
HasMany(x => x.ChildrenNodes)
.LazyLoad()
.KeyColumn("ParentId")
.Cascade.All();
Table("Category");
}
}
public class Category : Node
{
public virtual string AppId { get; set; }
public override string Title { get; set; }
public override int MaxDepth { get; set; }
public virtual Category Parent { get; set; }
public virtual IList<Category> ChildrenNodes { get; set; }
public virtual bool IsActive { get; set; }
}
public abstract class Node
{
public virtual long Id { get; set; }
public abstract string Title { get; set; }
public abstract int MaxDepth { get; set; }
}
Here is my testing code:
[Test]
public void CreateTableInDb()
{
using (var db = new FileDatabase(DbFileLocation, true))
{
var categoryMenu = new Category
{
AppId = "1",
MaxDepth = 3,
IsActive = true,
Title = "Services"
};
db.Create(categoryMenu);
categoryMenu.ChildrenNodes = new List<Category>
{
new Category
{
Title = "SubService-Level1",
Parent = categoryMenu,
}
};
db.Update(categoryMenu);
}
}
When i look into the table it's creating i have only one row,
with empty ParentId column.
How can i fix it and what i'm doing wrong?
first you'll missing .Inverse() on the hasmany. As it stands it will save and update the parentId twice
all collections should be readonly. NHibernate will replace them with tracking and lazyloading collections which you are throwing away. Change the code to
public class Category : Node
{
public Category()
{
// best practice so that nobody has to null check the collection
ChildrenNodes = new List<Category>();
}
public virtual IList<Category> ChildrenNodes { get; private set; }
public void Add(Category subcategory)
{
subcategory.Parent = this;
ChildrenNodes.Add(subcategory);
}
}
// in testcode
categoryMenu.Add(new Category { Title = "SubService-Level1" });
I am a newbie to Fluent Nhibernate and .NET. So please let me know if my question is not clear.
I have 3 tables in app as below
Table A
AID(PK), CreatedDate(PK), ZID, AFirstname, ALastname, AAddress, AZipCode
Table B
CID(PK), AID(PK), Date(PK), Field1, Field2
Table C
CID (PK), Cname
Please correct me if I am wrong. My Model Classes look like below.
public class A {
public A() {}
public virtual long AID { get; set; }
public virtual int ZID { get; set; }
public virtual DateTime CreatedDate { get; set; }
public virtual string AFirstName { get; set; }
public virtual string ALastName { get; set; }
public virtual string AZip { get; set; }
public virtual string AAddress { get; set; }
}
MapperClass for Class A
public class AMap : ClassMap<A> {
public AMap() {
Table("A");
CompositeId().KeyProperty(x => x.AID, "AID").KeyProperty(x => x.CreatedDate, "CreatedDate");
Map(x => x.ZID).Column("ZID").Not.Nullable();
Map(x => x.AFirstName).Column("AFirstname").Not.Nullable();
Map(x => x.ALastName).Column("ALastname").Not.Nullable();
//Same as above for Address and ZipCode
}
}
My B Model Class looks like below
public class B{
public B() { }
public virtual long AID { get; set; }
public virtual int CID { get; set; }
public virtual DateTime Date { get; set; }
public virtual string Field1 {get; set; }
public virtual string Field2 {get; set; }
}
Mapper Class for Class B
public class BMap : ClassMap<B> {
public BMap() {
Table("B");
CompositeId().KeyProperty(x => x.AID, "AID").KeyProperty(x => x.CID, "CID").KeyProperty(x => x.Date, "Date");
Map(x => x.Field1).Column("Field1").Not.Nullable();
//Same for Field2
}
}
My Table C Model Class looks like below.
public class C{
public C() { }
public virtual int C{ get; set; }
public virtual string Cname{ get; set; }
}
MapperClass for Class C
public class C: ClassMap<C> {
public C() {
Table("C");
Id(x => x.CID).GeneratedBy.Identity().Column("CID");
Map(x => x.CName).Column("Cname").Length(64);
}
}
Now many might argue that the table designs are not proper. But nothing can be done at this point and definitely this kind of design may degrade the performance but I guess we have to live with this for a little while.
Now I want some help in writing the mapping for all the three tables. Also can i use Criteria API to write a query for this to join all the 3 tables.
In my Application I get the ZID from another function. Now depending on the ZID i need to grab AFirstName, ALastName, Field1,Field2, CName. How can this be possible?
Please help. Also let me know if the problem is not clear.
Thanks in Advance.
replace the ids with references to the original properties so you can navigate them
public class B
{
public virtual A A { get; set; }
public virtual C C { get; set; }
public virtual string Field1 {get; set; }
public virtual string Field2 {get; set; }
}
public class BMap : ClassMap<B>
{
public BMap()
{
Table("B");
CompositeId()
.KeyReference(x => x.A, "AID", "Date")
.KeyReference(x => x.C, "CID");
Map(x => x.Field1, "Field1").Not.Nullable();
Map(x => x.Field2, "Field2").Not.Nullable();
}
}
// query for it
var results = session.CreateCritera<B>()
.JoinAlias("A", "a")
.JoinAlias("C", "c")
.SetProjection(Projections.List()
.Add(Projections.Property("Field1"), "Field1")
.Add(Projections.Property("Field2"), "Field2")
.Add(Projections.Property("a.CreatedDate"), "Date")
.Add(Projections.Property("c.Name"), "CName"))
.SetResulttransformer(Transformers.AliasToBean<YourDto>())
.List<YourDto>();