Получение NHibernate.Mappings.Attributes to work Options - PullRequest
2 голосов
/ 24 апреля 2009

Я использую v2.1 NHibernate.dll и NHibernate.Mappings.Attributes v2.1 в проекте.

Когда я запускаю код ниже, я получаю следующее исключение и буду благодарен за любые указатели. В том же проекте, если я удаляю атрибуты и использую файлы сопоставления 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: 

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

[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. Атрибуты должны быть созданы - исключение происходит до того, как файл создан (он не находится в выходном каталоге), и поэтому, к сожалению, я не могу опубликовать это.

Ответы [ 7 ]

2 голосов
/ 25 апреля 2009

Стюарт,

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

удалось заставить его работать с помощью:

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 голос
/ 15 марта 2011

Каждый раз, когда вы используете файл 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();
1 голос
/ 06 декабря 2010

Некоторое время 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 голос
/ 28 мая 2009

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

[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 голосов
/ 06 декабря 2010

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

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

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

0 голосов
/ 25 мая 2010

Как указано выше, вы должны указать имя класса начиная с версии 2 ... Я опубликовал статью о том, как обойти это, получив HbmWriter: http://blog.hopla.org/2009/12/fix-for-nhibernate-mapping-attributes-2-1/

0 голосов
/ 27 ноября 2009

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

[Class()]
public class Bar{}

Между тем, код ниже в порядке:

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

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

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

...