2009-06-25 2 views
1

NHibernate에서 "table per class hierarchy"전략을 사용하여 하나의 테이블에 객체 계층을 구현하려고합니다. 간단한 예제로 쉽게 재현 할 수있는 NHibernate 맵핑에 오류가 있습니다. 오류 :테이블 당 클래스 계층 전략을 사용하여 nhibernate에서 다중 레벨 클래스 계층 구조를 관리하는 방법은 무엇입니까?

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> 

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 

나는 다음과 같은 도메인 클래스와 함께이 문제를 재현 할 수 있습니다 잘못하고있는거야?

답변

5

에 거의 코드로 80 %를 매핑하기위한 매우 유용한 기본값을가 C# 및 NHibernate에 익숙하지만 Activity은 매핑에서 abstract="true"으로 설정해야합니까? Activity 클래스가 추상 클래스가 아닌 것 같습니다.

RunningTalkingActivity 안에 있어야합니다. 그렇지 않으면 StartTime이 저장되지 않습니다. 권리?

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

어쨌든 errormessage는 NHibernate가 in-statement로 일부 쿼리를 만들려고합니다. 그러나 그것에 대한 가치는 없습니다. 기본적으로 그것은 같은 것을 작성하려고합니다.

... 
WHERE foo IN (null) 

코드를 올바르게 구문 분석하면. 히트가이 오류를 throw 할 때 수행하려는 작업은 무엇입니까?

이미 최대 절전 모드 구성에서이 기능을 활성화하여 무슨 일이 일어나는지 확인하려고 했습니까?

<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 테이블 당 클래스 당 클래스에서 부모 테이블에서 상속 테이블로 1-1 FK를 사용하여 클래스 당 DB를 가져 오는 것을 의미합니다. 그때 discriminators 필요가 없습니다. IActivity를 매핑 할 필요도 없습니다 (세션이 직접 작동하지 않는다면, 다음에는 약간의 조정이 필요합니다).

은 어쨌든, 난 강력 나는 그것을 아니에요 당신은 매핑 슈퍼 간단하게 FluentNHibernate에서 들여다를 취할 것 제안하고, 모든

+0

전체 클래스 계층 구조에 대해 하나의 테이블을 가진 클래스 * 계층 구조 * 테이블을 참조하고 있습니다. 실제로 Fluent NHibernate를 살펴 봤지만 XML을 (관련 매뉴얼과 함께) 훨씬 쉽게 찾을 수 있도록 배우고 있습니다. 또한 정상이 아닌 물건을 처리해야하는 복잡한 객체 모델도 있습니다. –

+0

나는 아직까지 그렇게하지 않았다면 NH 사용자 그룹 (nhusers @ google groups)과 상담하는 것이 최선의 선택이라고 말할 수 있습니다. 그들은 NH 이용 팁에 도움이되는 매우 유용합니다 –

+0

NH의 공식적인 부분이 아니기 때문에 나는 Fluent로 전환하지 않을 것입니다, 심지어 공헌 패키지가 아닙니다. NH가 개발 중일 때 Fluent는 구식 일 것입니다. –

관련 문제