Search code examples
automapperfluentsharp-architecture

Fluent Automapper issue with tag creation


POST EDITED - see edit below

I have a query about the FLuent Automapping which is used as part of the SHarp Architecture. Running one of the tests cases will generate a schema which I can use to create tables in my DB.

I'm developing a site with Posts, and Tags associated with these posts. I want a tag to be able to be associated with more than one post, and for each post to have 0 or more tags.

I wanting to achieve a DB schema of:

Post {Id, Title, SubmitTime, Content}

Tag {Id, Name}

PostTag {PostId, TagId}

Instead, I'm getting:

Post {Id, Title, SubmitTime, Content}

Tag {Id, Name, PostID (FK)}

I'm using sharp architecture, and may classes look as follows (more or less):

public class Post : Entity
{
    [DomainSignature]
    private DateTime _submittime;
    [DomainSignature]
    private String _posttitle;

    private IList<Tag> _taglist;

    private String _content;

    public Post() { }

    public Post(String postTitle)
    {
        _submittime = DateTime.Now;
        _posttitle = postTitle;
        this._taglist = new List<Tag>();
    }


    public virtual DateTime SubmitTime { get { return _submittime; } private set { _submittime = value; } }

    public virtual string PostTitle { get { return _posttitle; } private set { _posttitle = value; } }

    public virtual string Content { get { return _content; } set { _content = value; } }

    public virtual IList<Tag> TagList { get { return _taglist; }  set { _taglist = value; } }




 public class Tag : Entity
{
    [DomainSignature]
    private String _name;

    public Tag() { }

    public Tag(String name)
    {
        this._name = name;
    }

    public virtual String Name
    {
        get { return _name; }
        private set { _name = value; }
    }

    public virtual void EditTagName(String name)
    {
        this.Name = name;
    }

}

I can see why it's gone for the DB schema set up that it has, as there will be times when an object can only exist as part of another. But a Tag can exist separately.

How would I go about achieving this? I'm quite new to MVC, Nhibernate, and SHarp architecture, etc, so any help would be much appreciated!

EDIT*

OK, I have now adjusted my classes slightly. My issue was that I was expecting the intermediate table to be inferred. Instead, I realise that I have to create it. So I now have (I've simplified the classes a bit for readability's sake.:

class Post : Entity
{
 [DomainSignature]
 String Title
 [DomainSignature]
 DateTime SubmitTime
 IList<PostTag> tagList

}

class Tag : Entity
{
[DomainSignature]
string name
}

class PostTag : Entity
{
[DomainSignature]
Post post
[DomainSignature]
Tag tag
}

This gives me the schema for the intermediate entity along with the usual Post and Tag tables:

PostTag{id, name, PostId(FK)}

The problem with the above is that it still does not include The foreign key for Tag. Also, should it really have an ID column, as it is a relational table? I would think that it should really be a composite key consisting of the PK from both Post and Tag tables.

I'm sure that by adding to the Tag class

IList<PostTag> postList

I will get another FK added to the PostTag schema, but I don't want to add the above, as the postList could be huge. I don't need it every time I bring a post into the system. I would have a separate query to calculate that sort of info.

Can anyone help me solve this last part? Thanks for your time.


Solution

  • Ok, I'd been led to believe that modelling the composite class in the domain was the way forward, but I finally come across a bit of automapper override code which creates the composite table without me needing to create the class for it, which was what I was expecting in the first place:

    public class PostMappingOverride : IAutoMappingOverride { public void Override(AutoMapping map) {

                map.HasManyToMany(e => e.TagList)
                   .Inverse()
                   .Cascade.SaveUpdate();
            }
        }
    

    This will now give me my schema (following schema non simplified):

    create table Posts (
        Id INT not null,
       PublishTime DATETIME null,
       SubmitTime DATETIME null,
       PostTitle NVARCHAR(255) null,
       Content NVARCHAR(255) null,
       primary key (Id)
    )
    
    create table Posts_Tags (
        PostFk INT not null,
       TagFk INT not null
    )
    
    create table Tags (
        Id INT not null,
       Name NVARCHAR(255) null,
       primary key (Id)
    )
    
    alter table Posts_Tags 
        add constraint FK864F92C27E2C4FCD 
        foreign key (TagFk) 
        references Tags
    
    alter table Posts_Tags 
        add constraint FK864F92C2EC575AE6 
        foreign key (PostFk) 
        references Posts
    

    I think the thrower is that I've been looking for a one-to-many relationship, which it is, but it is called HasManytoMAny here...