我遇到了 nHibernate 的问题:如果一个实体继承自一个基本实体,那么这个子实体不能被另一个实体引用。
我的数据库中有一个继承层次结构,如下所示:
VideoFeed
是一个VisualFeed
VideoFeed
有很多PlaylistAssignment
这是(转述的)SQL 定义
create table VisualFeed
(
id BIGINT NOT NULL -- Primary key
)
create table VideoFeed
(
id BIGINT NOT NULL -- Primary key, foriegn key references VisualFeed
)
create table PlaylistAssignment
(
id BIGINT NOT NULL, -- Primary key
VideoFeed_Id BIGINT NOT NULL -- Foreign key to VideoFeed
)
和类定义
public class VisualFeed
{
public virtual long? Id { get; set; }
}
public class VideoFeed : VisualFeed
{
public virtual ISet<PlaylistAssignment> PlaylistAssignments { get; set; }
}
public class PlaylistAssignment
{
public virtual long? Id { get; set; }
public virtual VideoFeed VideoFeed { get; set; }
}
VisualFeed
这是(父类)的映射代码:
public static void Map(ModelMapper mapper)
{
mapper.Class<DATMedia.CMS.EntityLibrary.Entities.VisualFeed>(
classMapper =>
{
classMapper.Table("cms_VisualFeed");
classMapper.Id(
visualFeed => visualFeed.Id,
idMapper =>
{
idMapper.Column("Id");
idMapper.Generator(Generators.HighLow,
generatorMapper =>
{
generatorMapper.Params(
new
{
max_lo = 256,
column = "NextHi",
where = "TableName='VisualFeed'"
}
);
}
);
}
);
});
}
这是映射代码VideoFeed
:
public static void Map(ModelMapper mapper)
{
mapper.JoinedSubclass<DATMedia.CMS.EntityLibrary.Entities.VideoFeed>(
joinedSubClassMapper =>
{
joinedSubClassMapper.Table("cms_VideoFeed");
joinedSubClassMapper.Key(keyMapper =>
{
keyMapper.Column("Id");
}
);
joinedSubClassMapper.Set(
playerGroup => playerGroup.PlaylistAssignments,
setPropertiesMapper =>
{
setPropertiesMapper.Key(
keyMapper =>
{
keyMapper.Column("VideoFeed_Id");
keyMapper.PropertyRef(videoFeed => videoFeed.Id);
}
);
setPropertiesMapper.Cascade(Cascade.All | Cascade.DeleteOrphans);
setPropertiesMapper.Inverse(true);
setPropertiesMapper.OrderBy(playlistAssignment => playlistAssignment.AssignmentRank);
},
collectionElementRelation =>
{
collectionElementRelation.OneToMany();
}
);
}
);
}
以及“PlaylistAssignment”的映射代码:
public static void Map(ModelMapper mapper)
{
mapper.Class<DATMedia.CMS.EntityLibrary.Entities.PlaylistAssignment>(
classMapper =>
{
classMapper.Table("cms_PlaylistAssignment");
classMapper.Id(
playlistAssignment => playlistAssignment.Id,
idMapper =>
{
idMapper.Generator(Generators.Identity);
}
);
classMapper.ManyToOne(
pa => pa.VideoFeed,
manyToOneMapper =>
{
manyToOneMapper.Column("VideoFeed_Id");
manyToOneMapper.Lazy(LazyRelation.Proxy);
}
);
});
};
调用时会抛出异常ModelMapper.CompileMappingForAllExplicitlyAddedEntities
。
在文件KeyMapper.cs中的 nHibernate 代码中引发异常:
public void PropertyRef(MemberInfo property)
{
if (property == null)
{
mapping.propertyref = null;
return;
}
if (!ownerEntityType.Equals(property.DeclaringType) && !ownerEntityType.Equals(property.ReflectedType))
{
throw new ArgumentOutOfRangeException("property", "Can't reference a property of another entity.");
}
mapping.propertyref = property.Name;
}
ownerEntityType
等于“VideoFeed”,并且两者都ReflectedType
等于DeclaringType
“VisualFeed”(父类名称)。即使这一切都是正确的,也会ArgumentOutOfRangeException
被抛出。
谁能想到解决方法?
稍后编辑此问题是由对setPropertiesMapper
. 它实际上是在我从问题中省略的另一个子类上(在简化问题的错误尝试中)。
真正的罪魁祸首是映射到下面的“cms_VisualFeedAssignment”:
mapper.Class<DATMedia.CMS.EntityLibrary.Entities.VisualFeed>(
classMapper =>
{
classMapper.Table("cms_VisualFeed");
classMapper.Id(
visualFeed => visualFeed.Id,
idMapper =>
{
idMapper.Column("Id");
idMapper.Generator(Generators.HighLow,
generatorMapper =>
{
generatorMapper.Params(
new
{
max_lo = 256,
column = "NextHi",
where = "TableName='VisualFeed'"
}
);
}
);
}
);
classMapper.Set<DATMedia.CMS.EntityLibrary.Entities.VisualFeedAssignment>(
visualFeed => visualFeed.Assignments,
bagPropertiesMapper =>
{
bagPropertiesMapper.Inverse(true);
bagPropertiesMapper.Lazy(CollectionLazy.Lazy);
bagPropertiesMapper.Key(
keyMapper =>
{
keyMapper.Column("VisualFeed_Id");
//keyMapper.PropertyRef<long?>(visualFeed => visualFeed.Id);
}
);
bagPropertiesMapper.Table("cms_VisualFeedAssignment");
},
collectionElementRelation =>
{
collectionElementRelation.OneToMany();
}
);
}
);
}
当我注释掉PropertyRef
电话时,它起作用了。