Question

I am working with NHibernate 3.3 and using the mapping-by-code system. The table/database I am working with is going to read-only for my application.

The problem I am facing is that my primary key column is stored as a binary field in SQL Server. I need to read this as a string, and unfortunately I cannot modify the table (including adding indexed views).

At this moment, I am trying to use an IUsertype to convert the value from binary to string. However, I am stuck when trying to set the type of an Id column in an entity to use an IUserType.

I have managed to successfully do it for normal properties as the below example, but can't figure out how to do it for ID columns and foreign key columns.

public class ExampleEntity
{
    public virtual String MyIdColumn { get; set; }
    public virtual Country Country { get; set; }
}


public class ExampleEntityMap : ClassMapping<ExampleEntity>
{

    public ExampleEntityMap()
    {
        Table("Table");

        Id(i => i.Id, map =>
        {
            map.Column("MyIdColumn");
            map.Type(???);
        });
        Property(i => i.Country, map =>
                                  {
                                      map.Column("Country");
                                      map.Type<CountryEnumUserType>();
                                  });
    }
}
  1. Is this possible with NH3.3 Mapping By Code?
  2. Must I implement an IIdentifierType instead to achieve what an IUserType does for an Id field?
  3. Can a NHibernate transformer achieve what I am doing?
  4. Is there another way to solve this? Other than retrieving the data and converting it in C#, as I have to do this for many columns in over a dozen tables.

Thanks

Was it helpful?

Solution

Figured it out. I ended up using the ComposedId property to map the Id column, which allows you to specify a IUserType for the Id column.

public class ExampleEntityMap : ClassMapping<ExampleEntity>
{
    public ExampleEntityMap()
    {
        Table("Table");

        ComposedId(i => i.Property(p => p.MyIdColumn, map =>
                                                    {
                                                        map.Column("MyIdColumn");
                                                        map.Type<MyIdColumnUserType>();
                                                    }));

        Property(i => i.Country, map =>
                              {
                                  map.Column("Country");
                                  map.Type<CountryEnumUserType>();
                              });
    }
}

OTHER TIPS

The solution you mentioned works althought a bit of a hack.

For it to work the entity also needs to override Equality / GetHashCode, something on the lines of:

    public override bool Equals(object obj)
    {
        return Country == (obj as ExampleEntity)?.Country;
    }

    public override int GetHashCode()
    {
        return this.Country.GetHashCode();
    }

And when loading using Get needs to be done using:

session.Get(new ExampleEntity{ Country = Countries.Kenya });

I will try to figure out a better solution and post it here.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top