I'm having a problem with my QueryOver and I don't understand why. My query returns the viewmodel object ContactInfo. I get this error on the Employee property: "could not find setter for property". How can I fill the Employee property within ContactInfo? What am I doing wrong?
ViewModel Object:
public class ContactInfo
{
public EmployeeInfo Employee { get; set; }
public string Email { get; set; }
public string InternalTelephone { get; set; }
}
Query
public override ContactInfo Execute()
{
ContactInfo r = null;
EmployeeInfo ei = null;
var result = Session.QueryOver<Job>()
.JoinAlias(j => j.EmployeeInfo, () => ei)
.Where(j => j.EmployeeInfo.Id == _employeeId)
.Select(
Projections.Property<Job>(j => ei.Id).WithAlias(() => r.Employee.Id),
Projections.Property<Job>(j => ei.FirstName).WithAlias(() => r.Employee.FirstName),
Projections.Property<Job>(j => ei.LastName).WithAlias(() => r.Employee.LastName),
Projections.Property<Job>(j => ei.ReferenceCode).WithAlias(() => r.Employee.ReferenceCode),
Projections.Property<Job>(j => j.Telefoon).WithAlias(() => r.InternalTelephone)
)
.TransformUsing(Transformers.AliasToBean<ContactInfo>())
.Take(1)
.SingleOrDefault<ContactInfo>();
var email = Session.QueryOver<Employee>()
.Where(e => e.Id == _employeeId)
.Select(e => e.Email)
.SingleOrDefault<string>();
result.Email = email;
return result;
}
}
What we can do is to use different than default result transformer, e.g. DeepTransformer.
In that case, the query must use Alias similar to the DTO model. So, if we have domain property ei.FirstName
belonging to JoinAlias - j.EmployeeInfo
- the alias must be reflecting the DTO ContactInfo - "EmployeeInfo.FirstName"
.Select(
Projections.Property<Job>(j => ei.FirstName) // the mapped domain model
.As("EmployeeInfo.FirstName"), // the path in DTO/view model
...
)
.TransformUsing(DeepTransformern<ContactInfo>()) // the DTO
So now, the path "EmployeeInfo.FirstName" will be used to populate the Employee
as a property EmployeeInfo
and its property FirstName
And this Result transformer
DeepTransformer will use Alias to build up the reference tree. Could be used for references/many-to-one
as well for IDictionary
... (but not for collections)
NOTE: The .Is()
method comes from some extensions, and can be replaced with != null
like
public static partial class Ext
{
public static bool Is(this object value)
{
return value != null;
}
....