代码之家  ›  专栏  ›  技术社区  ›  Bruno Reis

(fluent)nhibernate-问题映射ID

  •  1
  • Bruno Reis  · 技术社区  · 15 年前

    我在映射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成功地保存了EntityA,检索了数据库生成的ID,并相应地设置了EntityA.ID属性)。

    但是,没有创建EntityB(空数据库,日志不显示任何内容)。因此,在我看来,在通过“generatedby.foreign”(“id”)定义保存entityb时,nhibernate访问此属性时遇到问题。可能是因为属性“id”不是EntityA的直接属性,而是来自EntityBase,但是我所做的看起来是正确的。

    问题出在哪里?我怎么解决?

    谢谢!

    编辑: 这里,我展示一些堆栈跟踪,如果可能的话。 如您所见,它确实进行了级联,并且在另一个实体上进行了保存或更新。

    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...
    
    1 回复  |  直到 15 年前
        1
  •  4
  •   Dunc    15 年前

    这个 外国的 函数接受 而不是财产。

    首先,您需要从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");
        /* ... */
    }
    

    这个 设置属性 call避免nhibernate尝试映射两次ID字段(因此会爆炸)。