流利的Nhibernate ManyToMany集合 - 不保存关联

时间:2010-03-30 19:05:25

标签: c# nhibernate fluent-nhibernate

我无法理解为什么这不起作用..

我有一个相对干净的实体模型,包括用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时实际存储关联?

谢谢!

1 个答案:

答案 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”。