3

Fluent nHibernate using nHibernate v. 2.1.2.4, nHibernate.Linq v. 1.1.0.1001, and Fluent NHibernate v. 1.1.0.685.

I have a domain object with a DateTime field called DateOfEvent. This is an actual date/time field in the database. I've also added 2 new properties YearOfEvent which grabs the Year from the DateOfEvent field as well as MontOfEvent which grabs the Month from the DateOfEvent field.

public class Event
{
    public Event() { }
    public virtual Int32 Id { get; set; }
    public virtual String Title { get; set; }
    public virtual DateTime DateOfEvent { get; set; }
    public virtual Int32 YearOfEvent
    {
        get { return DateOfEvent.Year; }
    }
    public virtual Int32 MonthOfEvent
    {
        get { return DateOfEvent.Month; }
    }
    public virtual String Location { get; set; }
    public virtual String City { get; set; }
    public virtual String State { get; set; }
    public virtual String Zip { get; set; }
    public virtual String Description { get; set; }
    public virtual Boolean HasImage { get; set; }
    public virtual Boolean IsActive { get; set; }
}

However, when running this method:

public IList<Event> GetActiveEvents(int pageNumber, int pageSize, out int totalItems)
    {
        Int32 skip = Misc.NumberToSkip(pageNumber, pageSize);
        totalItems = (from e in _session.Linq<Event>()
                      where e.IsActive
                      select e).Count();

        return (from e in _session.Linq<Event>()
                where e.IsActive
                select e)
            .Skip(skip)
            .Take(pageSize)
            .ToList();
    }

NHibernate.QueryException: could not resolve property: YearOfEvent of: ....Event

FWIW, I've blurred out the name of the project. ;)

Any idea how to get this query working?

Thanks! -Steve

EDIT: Here's my mapping class:

public class EventMap : ClassMap<Event>
{
    public EventMap()
    {
        Table("tbl_event");
        Id(x => x.Id, "eventId");
        Map(x => x.DateOfEvent, "dateOfEvent");
        Map(x => x.Description, "description");
        Map(x => x.Title, "title");
        Map(x => x.Location, "location");
        Map(x => x.State, "state");
        Map(x => x.City, "city");
        Map(x => x.Zip, "zip");
        Map(x => x.HasImage, "hasImage");
        Map(x => x.IsActive, "isActive");
    }
}

...and my config:

public Configuration GetConfiguration()
    {
        Configuration configuration;
        var assembly = Assembly.Load(".....Data");
        var fluentConfig = Fluently.Configure()
                            .Database(MySQLConfiguration.Standard.ConnectionString(
                                          c => c.FromConnectionStringWithKey("......")
                                          ))
                            .Mappings(m => m.FluentMappings.AddFromAssembly(assembly));
        configuration = fluentConfig.BuildConfiguration();
        configuration.Properties.Add("hbm2ddl.keywords", "none");
        return configuration;
    }

I also just tried the Criteria API:

return _session.CreateCriteria(typeof (Event))
            .Add(Expression.Eq("IsActive", true))
            .Add(Expression.Eq("YearOfEvent", year))
            .List<Event>();

No workie either.

StephenPAdams
  • 2,797
  • 2
  • 30
  • 49
  • Strange. Looks fine to me, I wonder if maybe it's the LINQ provider trying to do something fancy with the properties. Have you tried running the same query without LINQ? – Phill Dec 14 '10 at 01:04
  • Phill, just tried (posted the query) using the Criteria API. Same exception. – StephenPAdams Dec 14 '10 at 01:35
  • Weird, Can't say I've ever come across such a problem before. Could you try removing the virtual off the two properties. Doubt it would help but worth a try. Other than that, I'm out of ideas for now sorry :( – Phill Dec 14 '10 at 02:16
  • Weird, can't say I've ever had such issues before. Could you try removing the virtual from the two properties. Not sure it will help, worth a try. Apart from that I'm out of ideas. My only other suggestion is trying the latest stable build from Fluent website. http://fluentnhibernate.org/downloads – Phill Dec 14 '10 at 02:19
  • Tried that already. Get this exception: The following types may not be used as proxies: ...Event: method get_YearOfEvent should be 'public/protected virtual' or 'protected internal virtual' ...Event: method get_MonthOfEvent should be 'public/protected virtual' or 'protected internal virtual' – StephenPAdams Dec 14 '10 at 02:20
  • It's like it's trying to map things it shouldn't be mapping... – Phill Dec 14 '10 at 02:27
  • Yeah, that's what I'm getting from it, too. FWIW, I've upgraded to NHibernate 3.0.0.0 and Fluent NHibernate 1.2 to no avail. – StephenPAdams Dec 14 '10 at 03:00
  • configuration.Properties.Add("hbm2ddl.keywords", "none"); <-- it's not this line is it? – Phill Dec 14 '10 at 03:23
  • Guys, it will not work unless you add both properties to the mapping b/c NH always includes the specified properies to a sql query but since these don't exist on a server you get the error. You should map your two properties (YearOfEvent & MonthOfEvent) and use a formula to provide their values or do filtering in Linq after you get the results. – Denis Ivin Dec 14 '10 at 03:52
  • If the properties are not specified in the mapping they shouldn't be included in the query. I've never had a problem with a class having properties that were not in the mapping. – Phill Dec 14 '10 at 04:36
  • @LookitsPuck looking at your Criteria API query, you've included the property that you can't query against. – Phill Dec 14 '10 at 04:49
  • Denis, thank you. What I ended up doing was just querying on e.DateOfEvent.Year and e.DateOfEvent.Month. How can I map these [MonthOfEvent and YearOfEvent] without causing issues and maintaining my logic? – StephenPAdams Dec 14 '10 at 05:29
  • @LookitsPuck - I've posted my solution (see answer below).. hope it helps! – Denis Ivin Dec 14 '10 at 21:54

5 Answers5

4

Here is how you can fix that using the formulas. In your Event class convert those 2 properties into regular properties:

public class Event
{
    public Event() { }
    ...
    public virtual DateTime DateOfEvent { get; set; }
    public virtual Int32 YearOfEvent{ get; set; }
    public virtual Int32 MonthOfEvent { get; set; }
    ...
    public virtual Boolean IsActive { get; set; }
}

Then in the mapping add formulas to populate their values.. I'm not very positive about the MySQL syntax for retrieving the year & month but you've got an idea (I used this reference):

public class EventMap : ClassMap<Event>
{
    public EventMap()
    {
        Table("tbl_event");
        Id(x => x.Id, "eventId");
        Map(x => x.DateOfEvent, "dateOfEvent");
        Map(x => x.YearOfEvent).Formula("SELECT YEAR(dateOfEvent)");
        Map(x => x.MonthOfEvent).Formula("SELECT MONTH(dateOfEvent)");            
        ...
        Map(x => x.IsActive, "isActive");
    }
}

Now you can query them just like any other fields using either LINQ or ICriteria:

return _session.CreateCriteria(typeof (Event))
            .Add(Expression.Eq("IsActive", true))
            .Add(Expression.Eq("YearOfEvent", year))
            .List<Event>();
Denis Ivin
  • 5,594
  • 1
  • 26
  • 25
2

You can query over properties that really exists in database or introduced in the mappings. As YearOfEvent just exists in your entity, you can not use it in your queries either in LINQ-to-NH or ICriteria.

Afshar Mohebi
  • 10,479
  • 17
  • 82
  • 126
2

The technique that I use is to force execution of NHLinq and then utilize LINQ to finish filtering. This is technically what needs to happen since NH is unaware of non-mapped properties like Event.YearOfEvent. It would look something like this:

_session.Linq<Event>()
.Where(e => e.IsActive)
.ToArray() // force evaluation of expression
.Where(e => e.YearOfEvent == DateTime.Now.Year); // evaluated by LINQ, not NHLinq

Note: You can utilize any of the other methods that force evaluation (e.g., ToList()). This technique is not dependent upon ToArray() specifically.

David Peden
  • 17,596
  • 6
  • 52
  • 72
1

Are you auto mapping this? Because I would suspect it's attempted to map YearOfEvent and MonthOfEvent, and it's trying to pull those columns from the database, but they don't exist.

If you're manually mapping them, then this wouldn't be an issue.

Phill
  • 18,398
  • 7
  • 62
  • 102
0

Your criteria query is not working, because your "YearOfEvent" property is not listed in your mapping. NHibernate does not know this property, and cannot translate it into a column name.

Try querying on properties that are actually mapped instead of calculated properties, or calculate the property directly in your query...

However, your linq query looks like it should be working, I don't see how this error can occur with that query & mapping...

Bertvan
  • 4,943
  • 5
  • 40
  • 61