2009-06-25 3 views
1

Я пытаюсь реализовать свою иерархию объектов в одной таблице с помощью стратегии «таблица для каждого класса» в NHibernate. Я получаю сообщение об ошибке с моим сопоставлением NHibernate, которое можно легко воспроизвести с помощью простого примера. Ошибка:Как управлять многоуровневой иерархией классов в nhibernate с помощью стратегии таблицы по иерархии классов?

System.NotSupportedException: Attempting to parse a null value into an sql string (column:activity0_.Type). 
at NHibernate.SqlCommand.InFragment.ToFragmentString() in InFragment.cs: line 109 
at NHibernate.Persister.Entity.SingleTableEntityPersister.DiscriminatorFilterFragment(String alias) in SingleTableEntityPersister.cs: line 551 

Я могу воспроизвести это со следующими классами домена:

public interface IActivity 
{ 
    Guid Id { get; set; } 
} 

public abstract class Activity : IActivity 
{ 
    public DateTime StartTime { get; set; } 
    public Guid Id { get; set; } 
} 

public class Running : Activity 
{ 
    public string Where { get; set; } 
} 

public class Talking : Activity 
{ 
    public string ToWhom { get; set; } 
} 

И следующие отображения XML:

<?xml version="1.0" ?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" 
        assembly="NHibernateTesting" 
        namespace="NHibernateTesting" > 
    <class name="IActivity" 
     lazy="false" 
     table="Activity" 
     discriminator-value="0" 
     abstract="true"> 
    <id name="Id"> 
     <generator class="guid" /> 
    </id> 
    <discriminator column="Type" type="Int16" /> 
    <subclass name="Activity" 
       discriminator-value="1" 
       abstract="true" 
       lazy="false"> 
     <property name="StartTime" /> 
    </subclass> 
    <subclass name="Running" 
       discriminator-value="2" 
       lazy="false" 
       extends="Activity"> 
     <property name="Where" /> 
    </subclass> 
    <subclass name="Talking" 
       discriminator-value="3" 
       lazy="false" 
       extends="Activity"> 
    <property name="ToWhom" /> 
    </subclass> 
    </class> 
</hibernate-mapping> 

Кто-нибудь есть идея о том, что я делать не так?

ответ

5

Я не то, что знакомы с C# и NHibernate, но вы уверены, что Activity должен быть установлен как abstract="true" в картографии? Похоже, класс Activity не является абстрактным.

Не должно быть Running и Talking проживает внутри Activity, иначе StartTime не будет сохранено. Правильно?

<subclass name="Activity" 
... 
    <subclass name="Running" 
    ... 
    </subclass> 
    <subclass name="Talking" 
    ... 
    </subclass> 
... 
</subclass> 

Как бы то ни было, ошибка в том, что NHibernate пытается создать запрос с помощью in-statement. Но для этого нет никаких значений. В основном он пытается что-то отличить

... 
WHERE foo IN (null) 

Если я правильно разобрал код. Что вы пытаетесь сделать, когда ударил эту ошибку?

Вы уже пытались включить их в конфигурацию спящего режима, чтобы проверить, что происходит?

<property name="show_sql">true</property> 
<property name="hibernate.format_sql">true</property> 
<property name="hibernate.use_sql_comments">true</property> 
+1

Думаю, это правильный ответ: вам нужно вложить элементы подкласса. Атрибут inherits предназначен для использования, если подклассы перемещаются в отдельный файл сопоставления. –

+0

Проблема не в том, что класс не объявляется абстрактным (хотя и хорошим catch), но с подклассом, который не является вложенным. Спасибо за помощь. Меня это несколько застопорило на несколько дней. –

2

afaik Table Per Class означает, что вы получаете таблицу в DB для каждого класса, с 1-1 FK из родительской таблицы в таблицы наследования. Тогда нет необходимости в дискриминаторах. Вам также не нужно отображать IActivity (если вы не намереваетесь, чтобы ваши сеансы работали напрямую против него, тогда вам нужна какая-то настройка).

Во всяком случае, я настоятельно рекомендую вам бы взглянуть на FluentNHibernate, что делает отображение супер просто, и очень полезные значения по умолчанию для отображения 80% практически без кода на всех

+0

Я имею в виду таблицу в иерархии классов *, которая имеет одну таблицу для всей иерархии классов. Я действительно посмотрел Fluent NHibernate, но я изучаю его, поэтому я нашел XML (с соответствующим руководством) намного проще. У меня также есть сложная объектная модель, где мне приходится иметь дело с вещами, которые не являются нормальными. –

+0

Я бы сказал, что ваш лучший вариант - проконсультироваться с группой пользователей NH (nhusers @ google groups), если вы еще этого не сделали. Они очень полезны там, в советах по использованию NH –

+0

Я бы не переключился на Fluent, потому что они не являются официальной частью NH, это даже не пакет взносов. Когда NH развивается, Fluent будет устаревшим. –

Смежные вопросы