Fluent Nhibernate Enum Mapping - nhibernate

I have some problem with enum mapping in fluent NHibernate. I know this question has been asked many times but I couldn't find any solution that worked for me. I'm newbie in NHibernate and it looks like I may have missed something simple and stupid. Here is my code.
public class DBPublication
{
public virtual int pub_id { get; set; }
public virtual PublicationStatuses status { get; set; }
...
}
public enum PublicationStatuses
{
on_moderation,
active,
...
}
public class DBPublicationMap : ClassMap<DBPublication>
{
public DBPublicationMap()
{
Table("content.publications");
Id(x => x.pub_id).GeneratedBy.Sequence("content.pub_sq");
Map(x => x.status);
...
}
}
postgres enum type
CREATE TYPE content.enum_publication_status AS ENUM('on_moderation', 'active', ...);
but when I try to save, postgres throws this
column "status" is of type content.enum_publication_status but expression is of type text
any suggestion?

Here is a working sample of configuring nhibernate to store enum field.
public class Entity
{
public virtual int id { get; set; }
public virtual SomeEnum EnumField { get; set; }
}
public enum SomeEnum
{
Value1,
Value2
}
class EntityMap : ClassMap<Entity>
{
public EntityMap()
{
Id(x => x.id).GeneratedBy.Native();
Map(x => x.EnumField);
}
}
class Program
{
static void Main(string[] args)
{
var factory = Fluently.Configure().Mappings(x => x.FluentMappings.AddFromAssemblyOf<Entity>())
.ExposeConfiguration(config => new SchemaExport(config).Create(false, true))
.Database(MsSqlConfiguration.MsSql2008.ConnectionString("Data Source=.;Initial Catalog=nhtest;Integrated Security=True"))
.BuildSessionFactory();
using (var session = factory.OpenSession())
{
using (var transaction = session.BeginTransaction())
{
var entity = new Entity();
entity.EnumField = SomeEnum.Value2;
session.Save(entity);
transaction.Commit();
}
}
}
}
In such case it is stored as strings in data base. If you want it be saved as integers, you need to change mapping for Enum field property to the following:
Map(x => x.EnumField).CustomType<int>();

Why are you creating enum types in progres? isn't this a maintenance-nightmare?
What does your configuration look like? Have you already tried using the conventions discribed here?
Looks like a simple casting error, so please consider using CustomType() / CustomSQLType() inside your mapping.

Simply add this class to your project:
public class PgEnumMapper<T> : NHibernate.Type.EnumStringType<T>
{
public override NHibernate.SqlTypes.SqlType SqlType
{
get { return new NHibernate.SqlTypes.SqlType(System.Data.DbType.Object); }
}
}
Then, you can use:
Map(x => x.status).CustomType<PgEnumMapper<PublicationStatuses>>();

Related

NH spatial and Fluent Mapping

I have read this in order to compile NH spatial for Nhibernate 3.1
http://build-failed.blogspot.it/2012/02/nhibernate-spatial-part-2.html
I have also read this
NHibernate.Spatial and Sql 2008 Geography type - How to configure
but the same code for me don't compile... I have this
using NetTopologySuite.Geometries;
namespace Core
{
public class District
{
public virtual int Id { get; set; }
public virtual Polygon Area { get; set; }
public virtual string Name { get; set; }
}
}
using Core;
using FluentNHibernate.Mapping;
namespace TestNHSpatial
{
public class DistrictMap : ClassMap<District>
{
public DistrictMap()
{
ImportType<NetTopologySuite.Geometries.Point>();
Id(x => x.Id);
Map(x => x.Name);
Map(x => x.Area).CustomType<Wgs84GeographyType>();
}
}
}
and this
[Serializable]
public class Wgs84GeographyType : MsSql2008GeographyType
{
protected override void SetDefaultSRID(GeoAPI.Geometries.IGeometry geometry)
{
geometry.SRID = 4326;
}
}
finally
var cfg = new OrderingSystemConfiguration();
var configuration = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008
.ConnectionString(connString)
.Dialect<MsSql2008GeographyDialect>())
.Mappings(m => m.AutoMappings.Add(
AutoMap.AssemblyOf<District>(cfg)))
.BuildConfiguration();
var exporter = new SchemaExport(configuration);
exporter.Drop(false, true);
exporter.Create(true, true);
i have this error...
NHibernate.MappingException : An association from the table District refers to an unmapped class: NetTopologySuite.Geometries.Polygon
can anyone help me?
thanks
UPDATE:
The code has some issues, namely:
You're using AutoMappings. You need to use custom mappings
You're using the wrong assembly when searching for the mappings
The export schema code is incorrect.
I'm the author of the blog post that you refer.
Change the type from Polygon (from NetTopologySuite) to IPolygon(from GeoAPI).
Should be something like this:
using GeoAPI.Geometries;
public class District
{
public virtual int Id { get; set; }
public virtual IPolygon Area { get; set; }
public virtual string Name { get; set; }
}
Anyway, if this doesn't work, send me a zip with a test project and I'll check it out.

Why doesn't this class hierarchy fluent mapping work?

What's wrong with my mapping shown below? Is this a problem with GeneratedBy.Foreign()? How should I use it cause my PK in UserTable(UID) is also the FK which refers to PersonTable PK(PID). I get the Duplicate class/entity mapping consoleMappingTest.SystemUser error. what do you suggest(be sure to look at database structure- no way to change it). thanks.
Inheritance structure:
public class Person
{
public virtual int ID { get; set; }
}
public class User:Person
{
public override int ID
{
get
{
return base.ID;
}
set
{
base.ID = value;
}
}
public virtual string Name { get; set; }
public virtual int Salary { get; set; }
}
public class SystemUser:User
{
public virtual int Password { get; set; }
}
Database structure:
for saving some info about person(some fields not shown here):
PersonTable(PID)
for saving User and all it's subclasses like system user:
UserTable(UID,Name,Salary,Type)
and here is my mapping:
public class PersonMap : ClassMap<Person>
{
public PersonMap()
{
Table("PersonTable");
Id(x => x.ID, "PID").GeneratedBy.Assigned();//or HiLo-not important
}
}
public class UserMap : ClassMap<User>
{
public UserMap()
{
Table("UserTable");
DiscriminateSubClassesOnColumn("Type").Default("U");
Id(x => x.ID, "UID").GeneratedBy.Foreign("Person");//how should use this?
Map(x => x.Salary);
Join("PTable", j =>
{
j.KeyColumn("UID");
j.Map(x => x.Name);
});
}
}
public class SystemUserMap : SubclassMap<SystemUser>
{
public SystemUserMap()
{
DiscriminatorValue("SU");
Map(x => x.Password);
}
}
Foreign("") is meant to point to a Reference (Property with another mapped entity) from which the Id should be retrieved. You don't have a Reference to class Person named Person so you can't use it like this.
you already asked the same question with an answer. I know i didn't do it right first shot but would be nice if you told me what doesnt work with the latest edit or you dont like the solution befor asking the same question again

Fluent Nhibernate - HQL select problem

I am new to NHibernate.
I am using Fluent Nhibernate and when I run a simple query I get null results.
Here is my configuration:
Fluent Configuration:
Fluently.Configure().Database(MsSqlConfiguration.MsSql2008
.ShowSql()
.ConnectionString(c => c
.FromConnectionStringWithKey("MY_DB")))
.Mappings(m =>m.FluentMappings.AddFromAssemblyOf<CsrDAL.Mappings.CsrRegistrationMap>())
.BuildSessionFactory();
Entity Class
public class Industry
{
public virtual int Id { get; private set; }
public virtual string Name { get; set; }
public virtual IList<CsrRegistration> ReferencedRegistrations { get; set; }
}
Map Class
public class IndustryMap : ClassMap<Industry>
{
public IndustryMap()
{
Table("industries");
Id(x => x.Id. "id");
Map(x => x.Name, "name");
}
}
Repository Fetch Method
public static IList<Industry> getData(CsrRegistration registration)
{
using (var session = CsrDalHelper.OpenSession())
{
using (var transaction = session.BeginTransaction())
{
try
{
IQuery q = session.CreateQuery("from Industry ind where ind.Id=1");
IList<Industry> inds =
q.List<Industry>();
return inds; // <-- This is null
}
}
}
}
Thank you in advance!
Dimitris
The problem was in session management, somewhere else in my code.
I was wrongly adding collection items to an entity outside the NH session.
As a newcomer to nhibernate, I am now studying the docs in more details.
Thank you

"No persister for" using Fluently mapping of Subclass in Fluent NHibernate

I'm doing a very basic thing with Fluent NHibernate. I found a lot of people with similar problems here in SO but none seemed to fix my problem.
I have 1 Class like:
public abstract class ParentClass
{
public virtual long Id { get; private set; }
public virtual DateTime CreateDate { get; set; }
public virtual int Type { get; set; }
}
And 1 Concrete classes like:
public class ChildClass : ParentClass
{
public virtual string PropertyX { get; set; }
public virtual int PropertyY{ get; set; }
}
So I made the mapping as follows:
public class ParentMap : ClassMap<ParentClass>
{
public ParentMap()
{
Id(x => x.Id);
Map(x => x.CreateDate);
DiscriminateSubClassesOnColumn("Type");
}
}
And
public class ChildMap : SubclassMap<ChildClass>
{
public ChildMap()
{
Extends<ParentClass>();
DiscriminatorValue(1);
Map(x => x.PropertyX);
Map(x => x.PropertyY);
}
}
My legacy database has 2 tables, 1 that holds all the data from the ParentClass and another one that holds the data from the Child with a foreign key in the ID.
The idea is to have different tables for each different implementation of the ParentClass but having the ParentClass table as a single repository for "Ids" and "Create Dates".
I'm creating my SessionFactory as follows:
private static ISessionFactory CreateSessionFactory()
{
return Fluently.Configure()
.Database(MsSqlCeConfiguration.Standard.ConnectionString(cstr => cstr.FromConnectionStringWithKey("TheConnectionString")))
.Mappings(mappings => mappings.FluentMappings.AddFromAssemblyOf<ParentClass>()
.ExportTo(#"c:\temp\Mappings"))
.BuildSessionFactory();
}
I'm doing just a basic test of storing things to the database as:
public void Store(ParentClass parent)
{
using (var session = sessionFactory.OpenSession())
{
using (var transaction = session.BeginTransaction())
{
session.SaveOrUpdate(parent);
transaction.Commit();
}
}
}
But despite the method waits for a ParentClass variable, I'm passing a ChildClass instance for it (the method is actually a inheritance of an interface, that's why it expects a ParentClass).
And every time I it raises an error on "SaveOrUpdate" method saying "No persister for: ChildClass".
What am I doing wrong?
ps.: Another strange thing is that even with the "ExportTo" method on the SessionFactory creation, no mapping is being write on the folder.
Change
.Mappings(mappings => mappings.FluentMappings.AddFromAssemblyOf<ParentClass>()
To
.Mappings(mappings => mappings.FluentMappings.AddFromAssemblyOf<ParentMap>()

Problem with Fluent nhibernate

i have written a code like this
public class person
{
public person()
{
public virtual int Id { get; set; }
public virtual string Code { get; set; }
}
}
public class Child : Person
{
public person()
{
public virtual string Name{ get; set; }
public virtual string Lastname{ get; set; }
}
}
public class Book
{
public virtual int Id { get; set; }
public virtual string Name {get;set;}
}
and my Mapper classes is like these
public class PersonMapping : ClassMap<Person>
{
public PersonMapping()
{
Table("tblPersons");
Id(x => x.Id).GeneratedBy.Native();
Map(p => p.Code);
JoinedSubClass<Child>("Id", MapChild);
}
public static void MapChild(JoinedSubClassPart<Child> child)
{
child.Table("tblChilds");
child.Map(p => p.Name);
child.Map(p => p.Lastname);
child.HasMany(x => x.Relatives);
}
}
public class RelativeMapping : ClassMap<Relative>
{
public RelativeMapping()
{
Table("tblRelatives");
Id(x => x.Id);
Map(p => p.Name);
References(x => x.Child).Column("ChildId");
}
}
this is Configuration
Assembly assm = Assembly.Load("BLL");
return Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008
.ConnectionString(c => c
.FromAppSetting("ConnStr"))
.Cache(c => c
.UseQueryCache()
.ProviderClass<HashtableCacheProvider>())
.ShowSql())
.Mappings(m => m.FluentMappings.AddFromAssembly(assm))
.BuildSessionFactory();
and this is the code of delete
public void Delete<T>(T obj)
{
ISessionFactory fact = FluentConfiguration.CreateSessionFactory();
ISession session = fact.OpenSession();
session.Delete(obj);
session.Flush();
}
my problem : when i wanna delete a Child it messages
" ILLEGAL ATTEMPT TO ASSOCIATE WITH TWO OPEN SESSION "
please help me
The error tells you the problem, and it is not with your entities or your mapping.
You have two or more open sessions and you're attempting to associate some entity with more than one of them.
update
In response to the updated code, I see that you have a method that accepts an entity as a parameter, creates a new session factory, creates a new session, and then tries to delete the entity.
There are some problems here:
You should only create the session factory once. Ever. This is an expensive operation.
You are passing the entity to the Delete() method. Where is this entity coming from? You've clearly already loaded it elsewhere in your application, using a different ISession. This is the crux of the problem. Unless you Evict() the entity from the first ISession (not recommended), trying to manipulate it with a different ISession will throw.
You're calling Flush() which should almost never be used.
You're using an implicit transaction.
You should really be deleting the entity with the same ISession with which it was loaded, and you should be performing work within a transaction, like this:
using(var transaction = session.BeginTransaction())
{
session.Delete(obj);
transaction.Commit();
}