views:

2953

answers:

5

I'm using v2.1 of NHibernate.dll and NHibernate.Mappings.Attributes v2.1 in a project.

When I run the code further below, I get the following exception, and will be grateful for any pointers. On the same project, if I remove the attributes and use xml mapping files, it works fine.

NHibernate.MappingException was unhandled 
Message="Could not compile the mapping document: 
DomainModel.hbm.xml" 
Source="NHibernate" 

InnerException: System.NullReferenceException 
Message="Object reference not set to an instance of an object." 
Source="NHibernate" 
StackTrace: 
at NHibernate.Cfg.XmlHbmBinding.ClassBinder.BindClass 
(XmlNode node, PersistentClass model) 
at NHibernate.Cfg.XmlHbmBinding.RootClassBinder.Bind 
(XmlNode node, HbmClass classSchema) 
at NHibernate.Cfg.XmlHbmBinding.MappingRootBinder.AddRootClasses(XmlNode 
parentNode) 
at NHibernate.Cfg.XmlHbmBinding.MappingRootBinder.Bind(XmlNode node) 
at NHibernate.Cfg.Configuration.AddValidatedDocument(NamedXmlDocument doc) 
InnerException:

I have a contact class as follows (Domain class has just one method, no properties):

[NHibernate.Mapping.Attributes.Class] 
public class Contact : DomainClass 
{ 
    [NHibernate.Mapping.Attributes.Id(Name = "Id")] 
    [NHibernate.Mapping.Attributes.Generator(1, Class ="Identity")] 
    public virtual int ID { get; set; } 

    [NHibernate.Mapping.Attributes.Property] 
    public virtual string Name { get; set; } 

    [NHibernate.Mapping.Attributes.Property] 
    public virtual string Town { get; set; } 
}

and session code as follows:

Configuration cfg = new Configuration(); 
cfg.Configure(); 
cfg.AddInputStream(NHibernate.Mapping.Attributes.HbmSerializer.Default.Serialize( 
typeof(Contact).Assembly), "DomainModel.hbm.xml"); 
_sessionFactory=cfg.BuildSessionFactory();

My hibernate.cfg.xml file is:

<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2"> 
<session-factory> 
<property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property> 
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</ 
property> 
<property name="connection.connection_string">Server=SERVER 
\EXPRESS2008;Initial Catalog=Contacts;Integrated Security=True</property> 
<property name="proxyfactory.factory_class">NHibernate.ByteCode.LinFu.ProxyFactoryFac­    tory, NHibernate.ByteCode.LinFu</property> 
</session-factory> 
</hibernate-configuration>
A: 

Stuart,

As I understand it,"DomainModel.hbm.xml" is the file NHibernate.Mappings.Attributes should create - the exception happens before the file is created (it's not in the output directory) and so unfortunately I can't post it.

cfg.AddInputStream takes two parameters: the IO stream containing the XML data, and a string ("DomainModel.hbm.xml" in your case) which is used to provide a stream name for reporting. IOW, you can take NHibernate.Mapping.Attributes.HbmSerializer.Default.Serialize() and write that stream out to a file.
Stuart Childs
+1  A: 

Stuart,

Thanks again for your response.

Managed to get it to work using:

using (MemoryStream stream = new MemoryStream()) 
{ 
HbmSerializer.Default.HbmNamespace = "NSpace.DomainLayer.Entities"; 
HbmSerializer.Default.HbmAssembly = "NSpace"; 
HbmSerializer.Default.Serialize(stream, 
System.Reflection.Assembly.GetExecutingAssembly()); 
stream.Position = 0; 
Configuration cfg = new Configuration(); 
cfg.Configure(); 
cfg.AddInputStream(stream); 
_sessionFactory = cfg.BuildSessionFactory(); 
}

and specifying table names in class attributes (my oversight as these were different from class names!).

Not sure why we need to specify Namespace separately, as I assumed NHibernate could work out the types to serialize from the assembly.

Hope above helps anyone experiencing similar issue, although my impression is few people are using NHibernate.Mappings.Attributes. The documentation seems to be seriously lacking.

Thanks very much for this - how did you figure it out?! This attributes support seems quite poorly designed and implemented to me; why do the attributes need to be given position integers? why does it generate XML instead of just programatically configuring the mappings directly? And why does it leave out information it can easily discover automatically?
Daniel Earwicker
A: 

If you did not solve yourt problem jet, try this

[NHibernate.Mapping.Attributes.Class(Table="youtable",NameType=typeof(Contact ))] public class Contact : DomainClass { [NHibernate.Mapping.Attributes.Id(Name = "Id")] [NHibernate.Mapping.Attributes.Generator(1, Class ="Identity")] public virtual int ID { get; set; }

[NHibernate.Mapping.Attributes.Property(Name="Name")] 
public virtual string Name { get; set; } 

[NHibernate.Mapping.Attributes.Property(Name="Town")] 
public virtual string Town { get; set; }

}

i'm using like this and it works fine .....

A: 

I must say that NHibnerate.Mapping.Atributes component was poorly written. The code below will lead to a generation of malformed mapping xml

[Class()]
public class Bar{}

Meanwhile, the code below is fine:

[Class(Name="Bar")]
public class Bar{}

Further more, if you place [Generator] attribute after [Id] attribute, then the information about generator will not be included in the xml, but place [Generator] before [Id] will do the jobs.

The 3.0 is under working and I hope that these "nasty" bugs will be fixed.

Mr Cold
A: 

As indicted above, you have to specify the class' Name since version 2... I have posted an article on how to work around this by deriving the HbmWriter: http://blog.hopla.org/2009/12/fix-for-nhibernate-mapping-attributes-2-1/

hopla