DataMigration N-N Relationship & Self reference

Topics: Core, Writing modules
Jan 5, 2012 at 2:24 PM
Edited Jan 5, 2012 at 2:54 PM

Hi,

I'm trying to persist an object to the database, but I'm having trouble creating the migration file.

My object is as follow: 

 
 
public class ItemPage
 {
        public virtual ItemPage Parent { get; set; }
        public virtual string Url { get; set; }
        public virtual List(ItemPage) Children { get; set; }
 }
(Children is a generic list of ItemPage)

So it's a n-n relationship and it's referencing itself. The DataMigration tool (codegen datamigration modulename) outputs something which somehow seems wrong:

SchemaBuilder.CreateTable("ItemPage", table => table
				.ContentPartRecord()
				.Column("Url", DbType.String)
				.Column("Parent_id", DbType.Int32)
			);

Some help would be really appreciated :)
Thanks
Jan 5, 2012 at 6:11 PM

The main thing that's wrong is that you migrate ItemPage as a ContentPartRecord, and yet ItemPage doesn't inherit from ContentPartRecord, which is needs to. Additionally there's a convention that ContentPartRecord classes should always end in "PartRecord", i.e. your class should be called ItemPagePartRecord. Finally your Children collection should be an IList not a List, and you need to populate it with an empty list in the constructor. See the article in Orchard docs for more relationship examples and explanations: http://docs.orchardproject.net/Documentation/Creating-1-n-and-n-n-relations

Jan 6, 2012 at 9:13 AM

I've already read the documentation a dozen time :) And still haven't figure out why I would need a contentPart and ContentPartRecord.

Actually, I think I don't. Anyways, I followed your advice and my class now looks like : 

public class PagePartRecord: ContentPartRecord {
        public virtual string url { get; set; }
        public virtual PagePartRecord Parent { get; set; }
        public virtual IList(PagePartRecord) Children { get; set; }

        public PagePartRecord()
        {
            Children = new List(PagePartRecord)();
        }
    }

And when I try to generate the Migration file, I end up with :

SchemaBuilder.CreateTable("PagePartRecord", table => table
				.ContentPartRecord()
				.Column("url", DbType.String)
				.Column("Parent_id", DbType.Int32)
			);

So, still the same problem.

Could you tell me what the migration file should look like based on my model ? Ideally I don't want to use a contentpartrecord... (or tell why I should :))

Thanks !

Jan 6, 2012 at 3:45 PM

If you don't want a ContentPartRecord don't use one. Content Parts are used to add additional fields, behaviours, templates etc. to a content type. If you're just performing your own database access then you need to define your own Id field, and use an IRepository<T> to access your records instead of using IContentManager. The 1-n and n-n documentation shows some examples based on ContentPartRecords, but they can apply equally well to any type of record (actually this is probably something that could be improved, IMO the tutorial should start with some simplest case data access before advancing onto content parts).

Jan 6, 2012 at 3:45 PM

By the way, what exactly do you think looks wrong about the migration, you still haven't said? It's perfectly correct according to your model.