views:

67

answers:

2

Background

Fluent NHibernate 1.1 (with a repository implementation using LINQ to NHibernate) in an ASP.NET MVC 2 project using Ninject.

I have a mapped class (Station) with a collection of another mapped class (Report). I would also like Station to have a convenience property (MostRecentReport) that returns the Report for that Station with the most recent timestamp.

Partial Schema

Stations
--------
Id

Reports
---------
Id
StationId
Timestamp

Partial Code

public abstract class Entity
{
    public virtual int Id { get; private set; }
}

public class Station : Entity
{
    public virtual IList<Report> Reports { get; private set; }

    public Station()
    {
        Reports = new List<Report>();
    }
}

public class Report : Entity
{
    public virtual Station Station { get; set; }
    public virtual DateTime Timestamp { get; set; }
}

public StationMap : ClassMap<Station>
{
    public StationMap()
    {
        Id(s => s.Id);
        HasMany<Report>(s => s.Reports)
            .Table("Reports")
            .KeyColumn("StationId");
    }
}

public ReportMap : ClassMap<Report>
{
    public ReportMap()
    {
        Id(r => r.Id);
        References<Station>(r => r.Station, "StationId");
        Map(r => r.Timestamp);
    }
}

I naively tried adding an unmapped property that returned Reports.OrderByDescending(r => r.Timestamp).FirstOrDefault() but that causes "could not resolve property: MostRecentReport" NHibernate.QueryExceptions (even though I am not using auto mapping). I also tried implementing it as a method with identical return, but that causes "Index was out of range" exceptions.

Is there a way to make it work with either the property (preferable) or method approach? Or is there some way to map it with Formula(), perhaps?

Update

Fluent NHibernate configuration (occurs in my NinjectModule implementation's Load override):

ISessionFactory sessionFactory = Fluently.Configure()
    .Database(MsSqlConfiguration.MsSql2008.ConnectionString(Settings.ConnectionString))
    .Mappings(m => m.FluentMappings.AddFromAssemblyOf<Domain.Station>())
    .BuildSessionFactory();
+1  A: 

I'm not sure that adding unmapped properties to your Entities is such a good idea. It's a better separation of concerns to add convenience properties to a ViewModel and use a repository query to get the value.

David Lynch
+1  A: 

There is no reason that you would have to map a property like this -- NHibernate should just ignore it if you are not automapping.

I happen to agree with David's answer, that you might be breaking the abstraction of your domain model.

That said, I think the answer is that you have an NHibernate query (HQL/Criteria/LINQ) somewhere (a repository?) that is trying to access this property. That is, it isn't in the mappings that is the problem, it is in trying to use MostRecentReport when querying the database/cache.

Jay
Yeah, I was ignorantly using MostRecentReport in an IQueryable constraint and NHibernate was barfing on it because it wasn't mapped. And you were both right that it was an unnecessary property. After I thought about it, it was a pretty simple query to get the same data from a Reports angle rather than a Stations angle.
Lobstrosity