【问题标题】:(Fluent) NHibernate - problem mapping Id(Fluent) NHibernate - 问题映射 Id
【发布时间】:2009-10-15 17:34:05
【问题描述】:

我在映射 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,检索了由数据库并相应地设置 entityA.Id 属性)。

但是,没有创建实体 B(空数据库,并且日志没有显示任何内容)。因此,在我看来,NHibernate 在通过“GeneratedBy.Foreign(“Id”)”定义保存 EntityB 时访问此属性时遇到问题。也许是因为属性“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...

【问题讨论】:

    标签: nhibernate fluent-nhibernate entity


    【解决方案1】:

    Foreign 函数采用 class 而不是属性。

    首先,你需要从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 字段(因此炸毁)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-03-15
      • 2011-08-08
      • 1970-01-01
      • 1970-01-01
      • 2011-07-17
      • 2011-04-10
      • 2010-11-30
      相关资源
      最近更新 更多