views:

125

answers:

2

Hello, I added some calculated read-only properties to my class and it's now throwing a QueryException: could not resolve property.

Here is my class (fake calculations right now):

public class IncompleteApplication : DealerBase
    {
        public virtual string Content { get; set; }
        public virtual string LegalBusinessName
        {
            get
            {
                return "Leg";
            }
        }
        public virtual string DbaName
        {
            get
            {
                return "Dba";
            }
        }
    }

Mapping:

public class IncompleteApplicationMap : DealerBaseMap<IncompleteApplication>
    {
        public IncompleteApplicationMap()
        {
            Schema("Dealer");
            Table("XmlSerialization");

            Map(app => app.Content);
        }
    }

And calling code:

data.GridDataItems = (from app in _Repository.GetAll()
                                  select new GridData.GridDataItem()
                                  {
                                      ID = app.Id,
                                      SubmittedDate = app.LastUpdated,
                                      UserName = app.User.UserName,
                                      LegalBusinessName = app.LegalBusinessName,
                                      DbaName = app.DbaName
                                  }).ToArray();

_Repository.GetAll() returns an IQueryable. When I add a .ToList() after GetAll() the code runs just fine (although I get a Select N + 1 situation).

Thanks for any help!

+1  A: 

You should map your two read-only properties with nhibernate and use a formula to provide their values while querying. I don't know fluent nh very well, but a standard xml mapping for your properties would look something like:

<property name="DbaName" access="readonly" insert="false" update="false" type="String" formula="(SELECT 'Dba')" />
DanP
That seems like a poor way of handling this. Why would I want my query to handle that? It seems that a better action would be to tell NHibernate that a field isn't mapped. Not sure if it's NHibernate or Linq thats hosing me over here.
Mike C.
@Mike: As far as I know, this is the only way to cleanly handle this with the current NH Linq provider (as unfortunate as it may be). Although not entirely desirable, this will allow you to query on those calculated fields in HQL/etc in addition to solving the problem with the linq provider...
DanP
Yikes. Hopefully somebody else will chime in.
Mike C.
@Mike: I guess I don't see the major problem with this (besides a little bit of duplication); using this method, the querying is the same on the client and server side - which is probably a desirable thing...
DanP
Let's say the formula because an entirely complicated formula... now you're requiring the database server to perform the operation that should have never gone there at all.
Mike C.
@Mike - fair enough, I'm watching this question with great interest as well, as I'm fairly certain that this is the only way to accomplish what you're looking for.
DanP
My hope is that there is a way to tell NHibernate "Hey dork, this is a readonly field and you don't need to worry about it."
Mike C.
I just ran into this as well. I have a feeling this is a Linq issue, I have seen it in other providers. If only we could explicitly inline functions... For your specific case, you may try to go to an array first with .GetAll().ToArray(). The array linq provider may be able to handle this.
oillio
A: 

nHibernate is generating a sql statement to execute on the server. Calculated fields don't exist in the db so you can't use them in your nHibernate query.

What you can do is execute the query to that meets all your criteria except those calculate fields, then after .ToArray() using linq on those object.

data.GridDataItems = (from app in _Repository.GetAll()
                                  select new GridData.GridDataItem()
                                  {
                                      ID = app.Id,
                                      SubmittedDate = app.LastUpdated,
                                      UserName = app.User.UserName,
                                  }).ToArray().Where(i=> i.LegalBusinessName = app.LegalBusinessName && i.DbaName = app.DbaName);
kareem