问题描述
我有一个映射Id的问题。实体的结构如下所示:pre $
public abstract class实体< TEntity,TId>
其中TEntity:实体< TEntity,TId>
{
public virtual TId Id {get;保护组}
public override bool Equals(object obj)...
...
}
public class EntityA< EntityA,long> :实体< EntityA,long>
{
public virtual EntityB B {get;私人设置}
/ * ... * /
}
public class EntityB< EntityA,long> :实体< 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。然后当我保存它时,我们可以使用这个方法来创建一个新的实体。
session.SaveOrUpdate(entityA);
NHibernate抛出一个异常,Unable to resolve property:Id。然而,我的日志显示一个EntityA被插入到数据库中,通过调试,我可以看到EntityA.Id被赋予一个值(即,nhibernate做了一个很好的工作,保存entityA,检索由数据库生成的Id,并相应地设置entityA.Id属性。)
但是,没有创建entityB(空数据库,日志没有显示)。所以,在我看来NHibernate在通过GeneratedBy.Foreign(Id)定义保存EntityB时遇到了问题。也许是因为属性Id不是直接属于EntityA的属性,而是来自EntityBase,但是我做的看起来正确。
问题在哪里?
谢谢!
编辑:
在这里,我将展示一些堆栈跟踪,如果它可能有所帮助。
你可以看到,它确实级联,才SaveOrUpdate的其他实体。
在NHibernate.Tuple .Entity.EntityMetamodel.GetPropertyIndex(String propertyName)
at NHibernate.Tuple.Entity.AbstractEntityTuplizer.GetPropertyValue(Object entity,String propertyPath)$ b $在NHibernate.Persister.Entity.AbstractEntityPersister.GetPropertyValue(Object obj,String propertyName的,EntityMode entityMode)
在NHibernate.Id.ForeignGenerator.Generate(ISessionImplementor sessionImplementor,obj对象)
:
。在NHibernate.Impl.SessionImpl.SaveOrUpdate(字符串的entityName,对象物OBJ)在NHibernate.Engine.CascadingAction.SaveUpdateCascadingAction.Cascade
(IEventSource会议,对象的孩子,字符串的entityName,任何对象,布尔isCascadeDeleteEnabled)在NHibernate.Engine.Cascade.CascadeToOne(对象的孩子,ITYPE型,CascadeStyle
风格,对象的东西,布尔isCascadeDeleteEnabled)
在NHibernate.Engine.Cascade.CascadeAssociation(Objec牛逼的孩子,ITYPE型,CascadeStyle风格,任何对象,布尔isCascadeDeleteEnabled)
在NHibernate.Engine.Cascade.CascadeProperty(对象的孩子,ITYPE型,CascadeStyle风格,任何对象,布尔isCascadeDeleteEnabled)$ b。在NHibernate的$ B。 Engine.Cascade.CascadeOn(IEntityPersister留存,父对象,对象的任何东西)
:
。在NHibernate.Impl.SessionImpl.SaveOrUpdate(obj对象)
在MyProject的...
首先,您需要从EntityB引用EntityA:
public class EntityB< EntityA,long> :Entity< EntityB,long>
{
//这是新的!
public virtual EntityA EntityA {get;私人设置}
/ * ... * /
}
这是EntityB的新映射文件:
public EntityBMap()
{
//第一个引用EntityA ...
引用(x => x.EntityA)
.SetAttributes(新属性
{
{insert,false},
{update,false}
});
// ...然后在外部函数中使用
Id(x => x.Id)
.GeneratedBy.Foreign(EntityA);
/ * ... * /
}
SetAttributes 呼叫避免NHibernate尝试映射Id字段两次(并因此炸毁)。
I have a problem mapping an Id. The structures of the entities are as follows:
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>
{
/* ... */
}
In my model, every EntityA must contain exactly one EntityB, and every EntityB that exists is there to be part of an EntityA. It's a common one-to-one relationship.
Now, to the mappings:
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");
/* ... */
}
}
Then I create an EntityA, that creates by itself an EntityB. Then when I save it
var entityA = EntityAFactory.CreateNewValidEntityA();
session.SaveOrUpdate(entityA);
NHibernate throws an exception, "Unable to resolve property: Id".
However, my log shows that an EntityA was "inserted" into the DB, and by debugging, I can see that EntityA.Id was attributed a value (ie, nhibernate did a good job saving entityA, retrieving the Id generated by the DB and setting the entityA.Id property accordingly).
However, no entityB was created (empty database, and log shows nothing). So, it looks to me that NHibernate had problems to access this property, when saving EntityB, through the "GeneratedBy.Foreign("Id")" definition. Maybe it's because the property "Id" is not directly a property of EntityA, but from EntityBase, however what I did looks correct to me.
Where is the problem? How can I solve it?
Thanks!
EDIT:Here I show some of the stack trace, if it might help.As you can see, it did Cascade, and it did SaveOrUpdate on the other entity.
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...
The Foreign function takes a class rather than a property.
Firstly, you need to reference EntityA from EntityB:
public class EntityB<EntityA, long> : Entity<EntityB, long>
{
// this is new!
public virtual EntityA EntityA { get; private set; }
/* ... */
}
Here's the new mapping file for 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");
/* ... */
}
The SetAttributes call avoids NHibernate trying to map the Id field twice (and hence blowing up).
这篇关于(流利)NHibernate - 问题映射Id的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!