Fluent Nhibernate ManyToMany 集合 - 不保存关联

发布于 2024-08-27 11:51:09 字数 2585 浏览 2 评论 0原文

我不明白为什么这不起作用。

我有一个相对干净的实体模型,由使用 DDD 创建的 POCO 组成(尽管可能不遵守大多数规则,甚至松散)。

我正在使用 Fluent NHibernate 来进行映射。我还使用 SchemaExport 创建数据库模式,只需我提供最少的关于如何执行此操作的输入。 NHibernate 可以自由选择最好的方式。

我有两个彼此具有多对多关系的实体(删除了不感兴趣的代码);媒体项和标签; MediaItems 可以有许多标签,标签可以应用于许多 MediaItems,并且我希望两侧都有集合,以便我可以轻松获取内容。

(下面有点格式问题,抱歉)

  • MediaItem:

    公共类 MediaItem
    {
    
    私有 IList<标签> _标签;
    
    公共虚拟长ID { 获取;放; }
    
    公共虚拟字符串标题 { get;放; }
    
    公共虚拟 IEnumerable;标签{获取{返回_tags; } }
    
    公共媒体项()
    {
        _tags = new List<标签>();
    }
    
    公共虚拟无效AddTag(标签newTag)
    {
        _tags.Add(newTag);
        newTag.AddMediaItem(this);
    }
    

    }

  • 标签:

    公共类标签 {

    私有IList _mediaItems;
    公共虚拟长ID { 获取;放; }
    公共虚拟字符串 TagName { get;放; }
    公共虚拟 IEnumerable; MediaItems { 获取 { 返回 _mediaItems; } }
    
    公共标签()
    {
        _mediaItems = new List();
    }
    
    protected inside 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 被保存,Tag 也被保存。然而,它们之间的关联却并非如此。 NHibernate 确实创建了关联表“MediaItemsToTags”,但它不会尝试向其中插入任何内容。

创建 ISessionFactory 时,我指定 ShowSQL() - 这样我就可以看到发送到 SQL 服务器的所有 DDL。我可以看到 MediaItem 和 Tag 表的插入语句,但没有 MediaItemsToTags 的插入。

我已经尝试过许多不同的版本,但我似乎无法破解它。级联是一个可能的问题,我尝试过两侧使用 Cascade.All() ,两侧使用 Inverse() 等,但没有骰子。

谁能告诉我什么是正确的方法来映射它以使 NHibernate 在我存储 MediaItem 时实际存储关联?

谢谢!

I can't get my head around why this isn't working..

I have a relatively clean entity model consisting of POCOs created with DDD in mind (while probably not following most rules even loosely).

I am using Fluent NHibernate to do the mapping. I am also using SchemaExport to create the database schema, with minimum input from me on how to do it. NHibernate is free to choose the best way.

I have two entities with Many-to-many relationships with each other (non-interesting code removed); MediaItem and Tag; MediaItems can have many tags, Tags can be applied to many MediaItems, and I want collections on both sides so I can easily get at stuff.

(A bit of a formatting issue below, sorry)

  • 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);
    }
    

    }

  • Tag:

    public class Tag
    {

    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);
    }
    

    }

I have tried to be smart about only exposing the collections as IEnumerable, and only allowing adding items through the methods. I also hear that only one side of the relationship should be responsible for this - thus the contrived AddMediaItem() on Tag.

The MediaItemMap looks like this:

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();
    }
}

The Tag mapping looks like this:

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();
    }
}

Now I have some test code that drops the database schema, recreates it (since I am shotgun debugging my brains out here), and then runs the following simple code:

Tag t = new Tag { TagName = "TestTag" };
MediaItem mi = new MediaItem { Title = "TestMediaItem" };

mi.AddTag(t);

var session = _sessionFactory.OpenSession();

session.Save(mi);

Yep, this is test code, it will never live past the problem in this post.

The MediaItem is saved, and so is the Tag. However, the association between them is not. NHibernate does create the association table "MediaItemsToTags", but it doesn't attempt to insert anything into it.

When creating the ISessionFactory, I specify ShowSQL() - so I can see all the DDL sent to the SQL server. I can see the insert statement for both the MediaItem and the Tag tables, but there is no insert for MediaItemsToTags.

I have experimented with many different versions of this, but I can't seem to crack it. Cascading is one possible problem, I've tried with Cascade.All() on both sides, Inverse() on both sides etc., but no dice.

Can anyone tell me what is the correct way to map this to get NHibernate to actually store the association whenever I store my MediaItem?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

春风十里 2024-09-03 11:51:09

您需要定义多对多表以及父键列和子键列:

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

You need to define the many-to-many table and parent and child key columns:

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();
    }
}

The syntax is identical in TagMap because both key columns are named "Id".

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文