The Free Nhibernate ManyToMany Collection - Not Rescue Associations

I can’t understand why this is not working.

I have a relatively clean entity model consisting of POCOs created with DDD in mind (although most of the rules are probably not respected even freely).

I am using Fluent NHibernate to do the mapping. I also use SchemaExport to create a database schema, with minimal input from me on how to do this. NHibernate may choose the best way.

I have two objects with many-to-many relationships with each other (non-interesting code is deleted); MediaItem and tag; MediaItems can have many tags, tags can be applied to many MediaItems, and I need collections on both sides, so I can easily get the material.

(A little bit about formatting 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 tried to be reasonable only to expose collections as IEnumerable and to allow adding elements only through methods. I also heard that only one side of the relationship should be responsible for this - thus the contrived AddMediaItem () on the tag.

The format of MediaItemMap is as follows:

 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 display is as follows:

 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 kind of test code that resets the database schema, recreates it (as I am debugging my shotgun with my shotgun 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); 

Yes, this is test code, it will never run into a problem in this post.

The MediaItem is saved as well as the tag. Meanwhile, the connection between them is not. NHibernate creates the association table "MediaItemsToTags", but does not attempt to insert anything into it.

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

I have experimented with many different versions of this, but I can't hack it. Cascading is one of the possible problems, I tried using Cascade.All () on both sides, inverting () on both sides, etc., but not playing dice.

Can someone tell me what is the right way to map this to force NHibernate to actually store the association whenever I store my MediaItem?

Thanks!

+4
source share
1 answer

You need to define the columns of the Many-to-Many and Parent and Child keywords:

 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, since both key columns are named "Id".

+1
source

Source: https://habr.com/ru/post/1305595/


All Articles