Relationship to Users

Feb 8, 2011 at 10:00 PM

Hi,

I am building a products' review module where only registered users can post review.s I have been reading the tutorial on 1-n relationships (http://orchardproject.net/docs/Creating-1-n-and-n-n-relations.ashx) but I have a couple of questions.

My ReviewPart part currently looks like this:

public class ReviewPartRecord : ContentPartRecord
    {
        public virtual UserPartRecord User { get; set; }
        public virtual string Subject { get; set; }
        public virtual string Comment { get; set; }
        public virtual int Vote { get; set; }
        public virtual int ProductId { get; set; }
        public virtual DateTime? ReviewDateUtc { get; set; }

    }

    public class ReviewPart : ContentPart<ReviewPartRecord>
    {
        public UserPartRecord User {
            get { return Record.User;  }
            set { Record.User = value; }
        }

        [Required]
        public string Subject
        {
            get { return Record.Subject; }
            set { Record.Subject = value; }
        }

        [Required]
        public string Comment
        {
            get { return Record.Comment; }
            set { Record.Comment = value; }
        }

        [Required]
        public int Vote
        {
            get { return Record.Vote; }
            set { Record.Vote = value; }
        }

        [Required]
        public int ProductId
        {
            get { return Record.ProductId; }
            set { Record.ProductId = value; }
        }

        public DateTime? ReviewDateUtc
        {
            get { return Record.ReviewDateUtc; }
            set { Record.ReviewDateUtc = value; }
        }
    }

The migration files looks like this

public int Create() {
            // Creating table ReviewPartRecord
            SchemaBuilder.CreateTable("ReviewPartRecord", table => table
                .ContentPartRecord()
                .Column("UserPartRecord_id", DbType.Int32)
                .Column("Subject", DbType.String, c => c.WithLength(100))
                .Column("Comment", DbType.String, c => c.WithLength(4000))
                .Column("Vote",DbType.Int32)
                .Column("ProductId", DbType.Int32)
                .Column("IsApproved", DbType.Boolean, c => c.WithDefault(true))
                .Column("ReviewDateUtc", DbType.DateTime, c => c.WithDefault(DateTime.UtcNow))
            );

For the User property in ReviewPart I am using UserPartRecord. To create the relationship, I am using the following column name UserPartRecord_id

Now, my problem is that whenever I try to save changes made in a form to create a review, I get the following message:

The column name is not valid. [ Node name (if any) = reviewpart2_,Column name = User_id ]

and I don't understand where/why is it trying to update a column named User_Id? I have searched my project and I don't have a reference to User_id. I am assuming this has to do with the relationship that I am trying to create but the column name is obviously incorrect. That make me think that the column name UserPartRecord_id is incorrect.

What would be the correct column name that I should use? or why does it try to update the column User_id?

Thanks in advance for your help.

Coordinator
Feb 8, 2011 at 10:51 PM

The migration logic is trying to match your column name with a property on your record and it fails because the name of the property is completely different. Column name and property name should be consistent.

Feb 9, 2011 at 5:57 PM

Thank you bertand. That solved my problem.

You guys have an excellent project going on!

Jun 17, 2011 at 2:20 PM
Edited Jun 17, 2011 at 2:32 PM

@gadwy: Can you post your final Migration/Model? I'm having a very similar issue at the moment despite following the instructions from Bertrand's post! Just need a bit of a sanity check :-)

Failing that - Bertrand, can you confirm that the property name on the ContentPartRecord should be UserPartRecord?

Thanks

Edit

My Migration is this:

SchemaBuilder.CreateTable("SomeRecord",
                table => table.Column("Id", column => column.Identity().PrimaryKey())
                              .Column("Name", column => column.NotNull())
                              .Column("UserPartRecord_Id"));

And the record looks like this:

public class SomeRecord
{
    public virtual int Id { get; set; }
    public virtual UserPartRecord UserPartRecord { get; set; }
    public virtual string Name { get; set; }
}
Does that look right? I'm running out of hair...

Jun 17, 2011 at 2:44 PM

That's not the case - the property will be matched by having the same type as the target record, the name shouldn't matter. That way you can have two different properties both joining to the same foreign table.

The main issue is:

.Column("UserPartRecord_Id"));

As far as I know it should be UserPartRecord_id - a lower case 'i' in id.

Jun 17, 2011 at 2:46 PM
Edited Jun 17, 2011 at 2:47 PM

Note: I might have got confused about what you were saying. But Bertrand was saying that as long as the Column name matches the name in your Record, it's fine. It doesn't matter whether they're called UserPartRecord or just User, so long as it's the same name in both migration and record, with _id appended.

Jun 17, 2011 at 3:06 PM

Pete, exactly as you suggested - UserPartRecord_id fixed it, I'd been using UserPartRecord_Id. Thanks ever so much!

In the same module I've got relationships to other records where the field names are called SomeOtherRecord_Id, WowYetAnotherRecord_Id with the capital I, and this is reflected in Creating 1-N and N-N Relations. Is there some rule that gets applied for record classes in the same module vs. those in different modules? I'm not aware of anything from my (limited) past experiences with NHibernate, and haven't come across this before in Orchard until I tried to create a relationship to UserPartRecord.

Jun 17, 2011 at 3:31 PM

Hmm ... I hadn't realised the n-n documentation had _Id. Actually I wasn't sure if the casing was the problem, but I had a situation once where it seemed to fix it, and I've seen a couple of other threads where it seemed to be the issue. So maybe the documentation needs fixing to show _id, even if it works in some cases. Actually I have a table in Mechanics where my key properties are called LeftContentItemId and RightContentItemId - but maybe its because I'm actually declaring them on the Record class that it works.