2009-09-09 7 views
1

ID 매핑 문제가 있습니다.(Fluent) NHibernate - 문제 매핑 Id

내 모델에서
public abstract class Entity<TEntity, TId> 
    where TEntity : Entity<TEntity, TId> 
{ 
    public virtual TId Id { get; protected set; } 
    public override bool Equals(object obj)... 
    ... 
} 

public class EntityA<EntityA, long> : Entity<EntityA, long> 
{ 
    public virtual EntityB B { get; private set; } 
    /* ... */ 
} 

public class EntityB<EntityA, long> : Entity<EntityB, long> 
{ 
    /* ... */ 
} 

, 모든 EntityA는 정확히 하나의 EntityB를 포함해야하며, 존재하는 모든 EntityB는 EntityA의 부분이 될 것입니다 : 다음과 같이 개체의 구조입니다. 일반적인 일대일 관계입니다. 매핑에 이제

:

public class EntityAMap : ClassMap<EntityA> 
{ 
    public EntityAMap() 
    { 
     Id(x => x.Id); 
     HasOne(x => x.B) 
      .Cascade.All(); 
     /* ... */ 
    } 
} 

public class EntityBMap : ClassMap<EntityB> 
{ 
    public EntityBMap() 
    { 
     Id(x => x.Id) 
      .GeneratedBy.Foreign("Id"); 
     /* ... */ 
    } 
} 

은 그 때 나는 자체 EntityB에 의해 생성하는 EntityA을 만들 수 있습니다. 나는 그것이

var entityA = EntityAFactory.CreateNewValidEntityA(); 
session.SaveOrUpdate(entityA); 

NHibernate에 예외를 throw 저장할 때 그런 다음, "없습니다 속성을 해결하려면 ID"를.

그러나 내 기록에 따르면 EntityA가 DB에 "삽입"되어 디버깅을 통해 EntityA.Id가 값 (즉, nhibernate가 엔티티 A를 저장하고 Id를 저장하는 데 성공했음을 알 수 있습니다. DB에 의해 생성되고 이에 따라 entityA.Id 속성이 설정 됨).

그러나 entityB가 생성되지 않았습니다 (빈 데이터베이스 및 로그는 아무것도 표시하지 않습니다). 그래서 NHibernate는 "GeneratedBy.Foreign ("Id ")"정의를 통해 EntityB를 저장할 때 NHibernate가이 속성에 액세스하는 데 문제가 있다고 생각합니다. 아마도 "Id"속성이 EntityA의 속성이 아니라 EntityBase에서 가져온 것일 수 있습니다. 그러나 내가 한 일은 나에게 맞습니다.

어디에 문제가 있습니까? 어떻게 해결할 수 있습니까?

감사합니다.

편집 : 여기서 도움이 될만한 스택 추적을 보여줍니다. 보시다시피, 그것은 캐스케이드를 수행하고 다른 엔티티에 SaveOrUpdate를 수행합니다.

at NHibernate.Tuple.Entity.EntityMetamodel.GetPropertyIndex(String propertyName) 
at NHibernate.Tuple.Entity.AbstractEntityTuplizer.GetPropertyValue(Object entity, String propertyPath) 
at NHibernate.Persister.Entity.AbstractEntityPersister.GetPropertyValue(Object obj, String propertyName, EntityMode entityMode) 
at NHibernate.Id.ForeignGenerator.Generate(ISessionImplementor sessionImplementor, Object obj) 
... 
at NHibernate.Impl.SessionImpl.SaveOrUpdate(String entityName, Object obj) 
at NHibernate.Engine.CascadingAction.SaveUpdateCascadingAction.Cascade(IEventSource session, Object child, String entityName, Object anything, Boolean isCascadeDeleteEnabled) 
at NHibernate.Engine.Cascade.CascadeToOne(Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled) 
at NHibernate.Engine.Cascade.CascadeAssociation(Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled) 
at NHibernate.Engine.Cascade.CascadeProperty(Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled) 
at NHibernate.Engine.Cascade.CascadeOn(IEntityPersister persister, Object parent, Object anything) 
... 
at NHibernate.Impl.SessionImpl.SaveOrUpdate(Object obj) 
at myproject... 

답변

4

외국 함수는 클래스보다는 속성을합니다.

첫째, 당신은 EntityB에서 EntityA를 참조해야합니다

public class EntityB<EntityA, long> : Entity<EntityB, long> 
{ 
    // this is new! 
    public virtual EntityA EntityA { get; private set; } 

    /* ... */ 
} 

여기 EntityB에 대한 새로운 매핑 파일의 다음 SetAttributes 호출 NHibernate에 두 번 ID 필드를 매핑하려고 피한다

public EntityBMap() 
{ 
    // first reference EntityA.... 
    References(x => x.EntityA) 
     .SetAttributes(new Attributes 
      { 
       {"insert", "false"}, 
       {"update", "false"} 
      }); 

    // ... then use it in the Foreign function 
    Id(x => x.Id) 
     .GeneratedBy.Foreign("EntityA"); 
    /* ... */ 
} 

(따라서 폭발).