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
ReflectedType
は「VideoFeed」に等しく、とは両方とも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
と、うまくいきました。