2009-04-24 3 views
2

Я использую v2.1 из NHibernate.dll и NHibernate.Mappings.Attributes v2.1 в проекте.Получение NHibernate.Mappings.Attributes для работы Опции

Когда я запускаю код ниже, я получаю следующее исключение и буду благодарен за любые указатели. В том же проекте, если я удалю атрибуты и использую файлы сопоставления xml, он отлично работает.

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: 

У меня есть класс контакта следующим образом (класс домена имеет только один метод, нет свойств):

[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; } 
} 

и код сеанса следующим образом:

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

Мой hibernate.cfg .xml-файл:

<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> 

Стюарт,

Как я понимаю, «DomainModel.hbm.xml» является файл NHibernate.Mappings.Attributes должен создать - исключение происходит до того, как файл будет создан (это не в выходной директории) и поэтому, к сожалению, я не могу опубликовать его.

+1

Не могли бы вы разместить файл DomainModel.hbm.xml? Сообщение об ошибке означает, что что-то отсутствует в файле сопоставления XML, когда он генерируется кодом атрибутов. –

ответ

2

Stuart,

Еще раз спасибо за ваш ответ.

Управляемый, чтобы заставить его работать, используя:

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(); 
} 

и задающие имена таблиц в атрибутах класса (мой надзор, поскольку они отличаются от имен классов!).

Не знаете, почему нам нужно указывать пространство имен отдельно, так как я предположил, что NHibernate может выработать типы для сериализации из сборки.

Надежда выше помогает любому, испытывающему подобную проблему, хотя мое впечатление мало кто использует NHibernate.Mappings.Attributes. Документация, похоже, серьезно отсутствует.

+1

Большое спасибо за это - как вы это поняли ?! Эта поддержка атрибутов кажется мне плохо разработанной и реализована; зачем атрибутам нужно задавать целые числа позиций? почему он генерирует XML, а не просто программно настраивает сопоставления напрямую? И почему он не учитывает информацию, которую он может легко обнаружить автоматически? –

1

Если вы еще не решили проблему еще, попробуйте этот

[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; } 
} 

я использую, как это и он работает отлично .....

+0

Это помогло. Мне нужен Class = "identity", по крайней мере, в моем спящем режиме 4.0.3 –

0

Я должен сказать, что NHibnerate.Mapping.Atributes компонент был плохо написан. ниже код приведет к генерации уродливы отображения XML

[Class()] 
public class Bar{} 

Между тем, следующий код отлично:

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

Более того, если вы размещаете [Generator] атрибут после [Id] атрибут , то информация об генераторе не будет включена в xml, но поместите [Generator], прежде чем [Id] выполнит задания.

3.0 работает, и я надеюсь, что эти «неприятные» ошибки будут исправлены.

0

Почти копия mitjast ответ «s, с незначительными исправлениями и форматированием:

[Class(NameType = typeof(DomainClass))] 
public class DomainClass 
{ 
    [NHibernate.Mapping.Attributes.Generator(Class = "guid")] 
    [NHibernate.Mapping.Attributes.Id(Name = "DomainID")] 
    public virtual Guid DomainID { get; set; } 
    [NHibernate.Mapping.Attributes.Property] 
    public virtual string Name { get; set; } 
} 

Это определение помог мне пройти через все исключения и генерировать действительное отображение НВМ. Как Г-н. Холодный указан, заказ Генератор и Идентификаторы имеют значение. Но в моем случае было обнаружено, что хотя для одного класса Id должен быть первым, чтобы быть упомянутым в hbm, для другого класса первый атрибут должен быть Генератор. Когда я изменяю порядок этих атрибутов в одном классе, так что оба класса имеют одинаковый порядок, hbm для одного из них становится неправильным ... Ситуация не изменилась после выпуска NHibernate.Mapping.Attributes-for-NHibernate -3.0.0.Alpha2. Присутствие таких причудливых вещей выглядит достаточно для меня, чтобы перейти к другому решению, к сожалению ...

1

Некоторое время NHMA не определяло имена классов, поскольку они теперь являются необязательными в NHibernate (в некоторых сценариях вы использовали бы вместо имени сущности). Самая последняя версия, однако, восстанавливает поведение автоматического обнаружения с настройкой, чтобы отключить ее при необходимости.

Атрибуты должны быть заказаны вручную, так как .NET не гарантирует их при компиляции (в отличие от Java).

Конечной целью NHMA является точное дублирование способа написания XML-версии; так что если у вас есть:

<something> 
    <innerData/> 
</something> 

версия NHMA будет:

[Something] 
    [InnerData(2)] 

NHMA пытается быть умным о выведении определенных значений (например, имена), но это будет только сделать так, если требуется значение ,

Он также предоставляет помощников, таких как NameType=typeof(XXX), чтобы воспользоваться функцией intellisense, выполнить проверку времени и рефакторинг.

Подробнее в документации: http://www.nhforge.org/doc/nh/en/index.html#mapping-attributes

1

Всякий раз, когда вы используете hbm.xml файл, который вы будете устанавливать свой класс конфигурации, как это:

Configuration cfg = new Configuration(); 
cfg.Configure(); 
// Add class mappings to configuration object 
cfg.AddAssembly(Assembly.GetCallingAssembly()); 
ISessionFactory sessionFactory = cfg.BuildSessionFactory(); 

Всякий раз, когда вы используете Nhibernate.Mapping.Attributes как classe вы будете использовать:

Например, вы используете Mapping.attributes в классе продукта

Configuration cfg = new Configuration(); 
cfg.Configure(); 

// Add class mappings attributes to configuration object 
cfg.AddInputStream(HbmSerializer.Default.Serialize(typeof(Model.Product); 
ISessionFactory sessionFactory = cfg.BuildSessionFactory();