views:

222

answers:

1

Dear ladies and sirs.

I have two entities types:

  • RunContainer parent entity type
  • Run child entity type

Run has a property Status, which is of type RunStatus, like so:

public enum RunStatus
{
  Created,
  Starting,
  // ...
}
public class Run
{
  public int ContainerId { get; private set; }
  // ...
  public RunStatus Status { get; private set; }
}

RunContainer has a calculated property ActiveRunCount, like so:

public class RunContainer
{
  public int Id { get; private set; }
  // ...
  public int ActiveRunCount { get; private set; }
}

In the mapping for the RunContainer.ActiveRunCount property, I use the formula specification like so:

<property name="ActiveRunCount" formula="(select count(r.Id) from Run r where r.ContainerId = Id and r.Status = 1)"/>

My problem is that I refer to the RunStatus enum values in the formula by their respective numeric value, rather than the appropriate symbolic name. Can anyone tell me how can I use the symbolic name instead?

Thanks.

A: 

NHibernate maps enums to the string representation if the SQL column is a string type, and this is the default if you let NHibernate generate the schema.

so:

ALTER TABLE Run ALTER COLUMN Status varchar(20)

and in the mapping

<class name="Run">
  <!- [...] -->
  <property name="Status"/>
</class>

Now the SQL table will contain a string representation of the enum. The formula can now query for it:

<property name="ActiveRunCount" formula="
  (select count(r.Id) from Run r 
  where r.ContainerId=Id and r.Status='Active')"/>

(If you already have data in the tables, you should write a conversion instead of the bare ALTER COLUMN statement).


EDIT after comment:

To generate the mapping file and make sure you have the enum value in the formula right, you could use FluentNhibernate. The mapping for the ActiveRun property would look like this:

Map(x => x.ActiveRunCount)
 .Formula(string.Format("(select count(r.Id) [...] and r.Status='{0}')",
   RunStatus.Active))

If that is what you were looking for, you could also keep the integers in the columns and do this:

Map(x => x.ActiveRunCount)
 .Formula(string.Format("(select count(r.Id) [...] and r.Status={0})",
   (int)RunStatus.Active))
Jan Willem B
Hi. Our schema was created manually, so the field is a smallint. But suppose it was a string. Does NHibernate validate that the given string actually denotes an existing value from the respective Enum type?
mark
NHibernate throws an exception if a string from the database column doesn't match a value from the enum. The formula, however, is a SQL statement, and is not validated in that way -- nhibernate will just copy the statement into the generated SQL. If you want to make sure you have a valid string there, you should use other ways of mapping which generate the mapping XML, like fluent mapping. With fluent mapping you can use code to define the mappings. I will add an example in my answer.
Jan Willem B
Thanks. It is too bad, that the core NHibernate does not allow to do this.
mark