我无法理解为什么这不起作用..
我有一个相对干净的实体模型,包括用DDD创建的POCO(虽然可能不会松散地遵循大多数规则)。
我正在使用Fluent NHibernate进行映射。我也使用SchemaExport来创建数据库模式,我最少的输入是如何做到的。 NHibernate可以自由选择最佳方式。
我有两个实体,彼此之间存在多对多关系(删除了非感兴趣的代码); MediaItem和Tag; MediaItems可以有很多标签,标签可以应用于很多MediaItems,我想要双方收藏,这样我就可以轻松搞定。
(下面有点格式化问题,抱歉)
MediaItem:
public class MediaItem
{
private IList<Tag> _tags;
public virtual long Id { get; set; }
public virtual string Title { get; set; }
public virtual IEnumerable<Tag> Tags { get { return _tags; } }
public MediaItem()
{
_tags = new List<Tag>();
}
public virtual void AddTag(Tag newTag)
{
_tags.Add(newTag);
newTag.AddMediaItem(this);
}
}
标签:
公共类标签 {
private IList<MediaItem> _mediaItems;
public virtual long Id { get; set; }
public virtual string TagName { get; set; }
public virtual IEnumerable<MediaItem> MediaItems { get { return _mediaItems; } }
public Tag()
{
_mediaItems = new List<MediaItem>();
}
protected internal virtual void AddMediaItem(MediaItem newItem)
{
_mediaItems.Add(newItem);
}
}
我曾试图将这些集合公开为IEnumerable,并且只允许通过这些方法添加项目。我也听说只有关系的一方应对此负责 - 因此在标签上设计了AddMediaItem()。
MediaItemMap如下所示:
public class MediaItemMap : ClassMap<MediaItem>
{
public MediaItemMap()
{
Table("MediaItem");
Id(mi => mi.Id);
Map(mi => mi.Title);
HasManyToMany<Tag>(mi => mi.Tags)
.Access.CamelCaseField(Prefix.Underscore)
.Cascade.SaveUpdate();
}
}
标记映射如下所示:
public class TagMap : ClassMap<Tag>
{
public TagMap()
{
Table("Tag");
Id(t => t.Id);
Map(t => t.TagName);
HasManyToMany<MediaItem>(mi => mi.MediaItems)
.Access.CamelCaseField(Prefix.Underscore)
.Inverse();
}
}
现在我有一些测试代码会丢弃数据库模式,重新创建它(因为我在这里调试我的大脑),然后运行以下简单代码:
Tag t = new Tag { TagName = "TestTag" };
MediaItem mi = new MediaItem { Title = "TestMediaItem" };
mi.AddTag(t);
var session = _sessionFactory.OpenSession();
session.Save(mi);
是的,这是测试代码,在这篇文章中永远不会超越问题。
保存MediaItem,标签也是如此。但是,他们之间的关联不是。 NHibernate会创建关联表“MediaItemsToTags”,但它不会尝试在其中插入任何内容。
创建ISessionFactory时,我指定ShowSQL() - 所以我可以看到发送到SQL服务器的所有DDL。我可以看到MediaItem和Tag表的insert语句,但没有MediaItemsToTags的插入。
我已尝试过许多不同版本,但我似乎无法破解它。级联是一个可能的问题,我尝试过两侧的Cascade.All(),两侧的反向()等,但没有骰子。
任何人都可以告诉我映射这个的正确方法是什么,以便NHibernate在我存储MediaItem时实际存储关联?
谢谢!
答案 0 :(得分:2)
您需要定义多对多表以及父键和子键列:
public class MediaItemMap : ClassMap<MediaItem>
{
public MediaItemMap()
{
Table("MediaItem");
Id(mi => mi.Id);
Map(mi => mi.Title);
HasManyToMany<Tag>(mi => mi.Tags)
.Table("MediaItemsToTags").ParentKeyColumn("Id").ChildKeyColumn("Id")
.Access.CamelCaseField(Prefix.Underscore)
.Cascade.SaveUpdate();
}
}
TagMap中的语法相同,因为两个键列都命名为“Id”。