1

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 に必ず 1 つの EntityB が含まれている必要があり、存在するすべての EntityB は EntityA の一部である必要があります。一般的な1 対 1 の関係です。

さて、マッピングに:

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 が DB に「挿入」されたことを示しており、デバッグによって、EntityA.Id が値に関連付けられていることがわかります (つまり、nhibernate は entityA を保存し、DB によって生成された Id を取得し、それに応じて entityA.Id プロパティを設定します)。

ただし、entityB は作成されませんでした (データベースは空で、ログには何も表示されません)。したがって、「GeneratedBy.Foreign("Id")」定義を使用して、EntityB を保存するときに、NHibernate がこのプロパティにアクセスする際に問題があったようです。プロパティ「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...
4

1 に答える 1

4

外部関数は、プロパティではなくクラスを取ります。

まず、EntityB から EntityA を参照する必要があります。

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 フィールドを 2 回マップしようとする (したがって、失敗する) のを回避できます。

于 2009-10-15T09:34:05.293 に答える