1

I have poco class

public class Category : Entity<int>
{
    public virtual Category Parent;
    public virtual Iesi.Collections.Generic.ISet<Article> Articles {get; set;}
    public virtual Iesi.Collections.Generic.ISet<Category> ChildCategories {get; set;}
}

I'm not sure is this correct mapping for ChildCategories property

public class CategoryMap : ClassMapping<Category>
{
    public CategoryMap()
    {
       ...
       Set(x => x.ChildCategories,
          c => { c.Cascade(Cascade.DeleteOrphans); },
          r => { r.OneToMany(); }              
       );
    }
}

Any child category can have only one parent. Once more is this correct mapping? If you need more information please ask.

Update: Exception inner message is following

{"Could not determine type for: xxxx, 
for columns: NHibernate.Mapping.Column(Parent)"}

Update 2:

public class CategoryMap : ClassMapping<Category>
    {
        public CategoryMap()
        {
            Id(x => x.Id, m => m.Generator(Generators.GuidComb));

            Property(x => x.Name, m =>
            {
                m.Length(255);
                m.NotNullable(true);
            });

            Property(x => x.Parent, m =>
            {
                //m.NotNullable(true);
            });

            Set(x => x.ChildCategories,
              c => 
              { 
                c.BatchSize(25);
                c.Inverse(true);
                c.Cascade(Cascade.DeleteOrphans); 
                c.Key(k =>
                {
                    k.Column("ParentId");
                });
              },
              r => { r.OneToMany(); }              
           );


            Set(x => x.Articles,
              c => { c.Cascade(Cascade.DeleteOrphans); },
              r => { r.OneToMany(); }
            );            
        }
    }

Update 3

Property(x => x.Parent, m =>
            {
                m.Column("ParentId");
                m.NotNullable(true);
            });

Error

{"Could not determine type for: xxxx, 
for columns: NHibernate.Mapping.Column(ParentId)"}
user1765862
  • 13,635
  • 28
  • 115
  • 220

1 Answers1

4

Not so sure what the real issues is, but my standard xml mapping for parent-child collection would look like this:

<set name="ChildCategories" lazy="true"  batch-size="25" inverse="true">
  <key column="ParentId" />
  <one-to-many class="Category"/>
</set>

While lazy is (as far as I remember) default, I prefer explicit statements

I would say, that really essential is the information where to search for a Parnet column. This I would mapp for sure explicitly. And also the inverse and batch-size. So, following

This could be the mapping of the set

 ...
 Set(x => x.ChildCategories,
      c => 
      { 
        c.BatchSize(25);
        c.Inverse(true);
        c.Cascade(Cascade.DeleteOrphans); 
        c.Key(k =>
        {
            k.Column("ParentId");
        };
      },
      r => { r.OneToMany(); }              
   );

Few more information about why to use batch-sizing: How to Eager Load Associations without duplication in NHibernate?

Because we used (in my snippet) the Inverse ... the Parent must be mapped as well (and assigned)

UPDATE: The essential part of this mapping is the Parent mapping!

But Parent is not a value type property. It is a reference. That's why we have to map it like this:

ManyToOne(x => x.Parent, m =>
{

See: Mapping-by-Code - ManyToOne

we cannot use

// NOT correct mapping
Property(x => x.Parent
Community
  • 1
  • 1
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • thanks, I updated code buut I'm still getting message Could not determine type for: xxxx, for columns: NHibernate.Mapping.Column(Parent)"} – user1765862 Apr 29 '14 at 07:20
  • Could you, please, show your latest complete mapping? I suggest that you should have map for `Parent` and `Children`. Both of them. And you should use explicit ` – Radim Köhler Apr 29 '14 at 07:33
  • It has sense :) I've posted those properties on the first place. Posted above as second update. – user1765862 Apr 29 '14 at 07:35
  • I can see your updated mapping. The column of the `Parent` is missing. It should also be mapped to column **ParentId**. This column (ParentId) plays two roles. It is a reference column for many-to-one and also the key column for one-to-many. Then it should be working properly. Is not it?. *NOTE please, take a look here http://nhforge.org/doc/nh/en/index.html#example-parentchild to get clear idea what we have to map, it is not so much, but some parts are essential* – Radim Köhler Apr 29 '14 at 07:36
  • I'm using ModelMapperWithNamingConventions to generate column names in db, but it should match with ParentId cause it's exactly column name which should be generated. – user1765862 Apr 29 '14 at 07:51
  • I was blind for a while, I did not expected that... see my updated answer ... ;) ;) now it WILL work ;) – Radim Köhler Apr 29 '14 at 07:52
  • It's working now, can you confirm me that this is ok ManyToOne(x => x.Parent, m => { m.Column("ParentId"); m.NotNullable(true); }); – user1765862 Apr 29 '14 at 07:55
  • NOOOOO it is bad! Parent id MUST be Nullable! The root parent will never have parent right? ;) – Radim Köhler Apr 29 '14 at 07:56