views:

100

answers:

2

I'm building an ecommerce site using S#arp Architecture. I'm trying to map a hierachy of categories and retrieve the top level categories. I'm using NHibernate.Linq for this. I have the following entity:

public class Category : Entity
{
    #region Properties
    [DomainSignature]
    [NotNullNotEmpty]
    public virtual string Name { get; set; }
    public virtual string Description { get; set; }
    public virtual int ListOrder { get; set; }

    public virtual IList<Product> Products { get; set; }
    public virtual IList<Category> ParentCategories { get; set; }
    public virtual IList<Category> ChildCategories { get; set; }
    #endregion

    public Category()
    {
        Products = new List<Product>();
        ParentCategories = new List<Category>();
        ChildCategories = new List<Category>();
    }
}

with the following Fluent NHibernate mapping:

public class CategoryMap : ClassMap<Category>
{
    public CategoryMap()
    {
        Id(x => x.Id);
        Map(x => x.Name);

        HasManyToMany(p => p.Products)
            .Cascade.All()
            .Table("CategoryProduct");

        HasManyToMany(c => c.ParentCategories)
            .Table("CategoryHierarchy")
            .ParentKeyColumn("Child")
            .ChildKeyColumn("Parent")
            .Cascade.SaveUpdate()
            .AsBag();


        HasManyToMany(c => c.ChildCategories)
            .Table("CategoryHierarchy")
            .ParentKeyColumn("Parent")
            .ChildKeyColumn("Child")
            .Cascade.SaveUpdate()
            .Inverse()
            .LazyLoad()
            .AsBag();
    }
}

I want to retrieve the root categories. I know I have eight in my db so here's my test:

[Test]
public void Can_get_root_categories()
{
    // Arrange
    var repository = new CategoryRepository();

    // Act
    var rootCategories = repository.GetRootCategories();

    // Assert
    Assert.IsNotNull(rootCategories);
    Assert.AreEqual(8, rootCategories.Count());
}

I figure I just get all Categories where the ParentCategories list is empty (initialized in the ctor of Category). So here's my repository method:

public IQueryable<Category> GetRootCategories()
{
    var session = NHibernateSession.Current;

    // using NHibernate.Linq here
    var categories = from c in session.Linq<Category>()
                     where c.ParentCategories.Count == 0
                     select c;
    return categories;
}

When I run my test I get "NHibernate.QueryException : could not resolve property: ParentCategories.Id of: MyStore.Core.Category"

What am I doing wrong?

Here are related questions, but didn't quite solve my problem:

http://stackoverflow.com/questions/1811316/fluent-nhibernate-need-help-with-manytomany-self-referencing-mapping

http://stackoverflow.com/questions/3010634/querying-a-self-referencing-join-with-nhibernate-linq

http://stackoverflow.com/questions/2054689/fluent-nhibernate-manytomany-self-referencing-mapping

Edit:

I think the problem lies with the .count in the Linq expression. This post related to this, but I'm not sure how to progress...

A: 

Got it. The problem was in the linq expression. It didn't like .Count for some reason. This might be a bug in NHibernate.Linq (NH2), but I hear NH3 linq is rock solid now.

Anyway, my solution is to use a Criteria instead:

var categories = session.CreateCriteria(typeof (Category)) .Add(Restrictions.IsEmpty("ParentCategories")) .List();

Thanks to a blog post by nixsolutions.com for getting me on the right track. All green again.

mattRo55
A: 

You should be using the Count() extension method instead of the Count property. This works fine in NHibernate 2.

Regards Jon

Jon
Hi Jon. I still get a fail with the same error msg when I use: var categories = session.Linq<Category>().Where(c => c.ParentCategories.Count() == 0).ToList(); (...looking forward to Sharp Arch 2 :)
mattRo55