(Свободно) NHibernate - идентификатор отображения проблем

У меня проблема с отображением идентификатора. Структуры субъектов следующие:

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 хорошо сохранил entityA, получив идентификатор, сгенерированный БД, и соответствующим образом установив свойство entityA.Id).

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

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

Спасибо!

РЕДАКТИРОВАТЬ: Здесь я показываю некоторую трассировку стека, если это может помочь. Как видите, он сделал 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...

person Bruno Reis    schedule 09.09.2009    source источник


Ответы (1)


Функция Foreign принимает класс, а не свойство.

Во-первых, вам нужно сослаться на 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 (и, следовательно, взрыва).

person Dunc    schedule 15.10.2009