2009-09-09 2 views
1

У меня проблема с отображением идентификатора. Структуры организаций заключаются в следующем:(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"); 
     /* ... */ 
    } 
} 

Затем я создаю EntityA, который создает по себе является EntityB. Затем, когда я сохранить его

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

NHibernate бросает исключение, "Не удается разрешить свойство: Id".

Однако мой журнал показывает, что EntityA «вставлен» в БД, и, отлаживая, я вижу, что EntityA.Id было приписано значение (т. Е. Nhibernate выполнил хорошую работу с сохранением объекта A, извлечение идентификатора созданный БД и соответствующим образом устанавливающий свойство entityA.Id).

Однако, сущностьБ не была создана (пустая база данных и журнал ничего не показывает). Таким образом, мне кажется, что NHibernate имел проблемы с доступом к этому свойству при сохранении EntityB через определение «GeneratedBy.Foreign (« Id »). Может быть, это потому, что свойство «Id» напрямую не является свойством EntityA, но из EntityBase, однако то, что я сделал, выглядит правильно для меня.

Где проблема? Как я могу это решить?

Спасибо!

EDIT: Здесь я показываю некоторые трассировки стека, если это может помочь. Как вы можете видеть, он сделал Cascade, и он сделал 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

Внешняя функция принимает класс, а не собственность.

Во-первых, вы должны ссылаться на EntityA из EntityB:

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

    /* ... */ 
} 

Вот новое отображение файлов для EntityB:

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"); 
    /* ... */ 
} 

SetAttributes вызов избегает NHibernate пытается отобразить поле Id дважды (и, следовательно, взорвать).