views:

60

answers:

1

In the CategoriesTranslated collection i have this error: illegal access to loading collection.

 public class Category : Entity
{
    public Category()
    {
        CategoriesTranslated = new List<CategoryTranslated>();

    }

    public virtual Category Parent { get; set; }
    public virtual string Name { get; set; }
    public virtual IList<CategoryTranslated> CategoriesTranslated { get; set; }
}

public class CategoryTranslated : Entity
{
    public CategoryTranslated()
    {
    }

    public virtual Category Category { get; set; }
    public virtual LanguageType Language { get; set; }
    public virtual string Name { get; set; }
}


   public void Override(AutoMapping<Category> mapping)
    {
        mapping.HasMany(x => x.CategoriesTranslated)
            .Inverse()
            .Cascade.All();

    }

  public void Override(AutoMapping<CategoryTranslated> mapping)
    {
        mapping.References(x => x.Category);
    }




CREATE TABLE Category(

[Id] smallint primary key identity(1,1), [Parent] smallint null, [Name] varchar(50) not null unique, ) alter table [Category] add CONSTRAINT fk_Category_Category
FOREIGN KEY(Parent) references Category (Id) go

CREATE TABLE CategoryTranslated(

[Id] smallint primary key identity(1,1), [Category] smallint not null, [Language] tinyint not null, [Name] varchar(50) not null, )

alter table [CategoryTranslated] add CONSTRAINT fk_CategoryTranslated_Category  

FOREIGN KEY(Category) references Category (Id) go

Where is it wrong? thank you

UPDATE The links to the hbm generater:

Category:
http://uploading.com/files/fmb71565/SubmitSiteDirectory.Core.Category.hbm.xml/

CAtegory translated: http://uploading.com/files/9c9aaem9/SubmitSiteDirectory.Core.CategoryTranslated.hbm.xml/

+1  A: 

I am guessing it has to do with the creation of the list inside the constructor, especially if you left a default ctor for NHib. And that NHib is trying to set the list before it's created. The other complication here is that you have a bi-directional relationship, and CategoryTranslated may be trying to get at the list before its created too.

I doubt this is the only solution, but here is a pattern I use that should solve the error:

    /// <summary>Gets the ....</summary>
    /// <remarks>This is what is available to outside clients of the domain.</remarks>
    public virtual IEnumerable<CategoryTranslated> CategoriesTranslated{ get { return _InternalCategoriesTranslated; } }

    /// <summary>Workhorse property that maintains the set of translated categories by:
    /// <item>being available to <see cref="Category"/> to maintain data integrity.</item>
    /// <item>lazily instantiating the <see cref="List{T}"/> when it is needed.</item>
    /// <item>being the property mapped to NHibernate, the private <see cref="_categoriesTranslated"/> field is set here.</item>
    /// </list>
    /// </summary>
    protected internal virtual IList<Category> _InternalCategoriesTranslated
    {
        get { return _categoriesTranslated?? (_categoriesTranslated= new List<Category>()); }
        set { _categoriesTranslated= value; }
    }
    private IList<StaffMember> _categoriesTranslated;

Now you need to set your mapping to access the private field, so assuming you use my casing preferences here, you'd have:

public void Override(AutoMapping<Category> mapping)
{
    mapping.HasMany(x => x.CategoriesTranslated)
        .Inverse()
        .Access.CamelCaseField(CamelCasePrefix.Underscore)
        .Cascade.All();
}

HTH,
Berryl

EDIT ============

The _Internal collection also gives the child of of the bi-directional relationship, CategoryTranslated in this case, a hook, as shown in the code below:

    public virtual CategoryTranslated CategoryTranslated
    {
        get { return _categoryTranslated; }
        set
        {
            if (_categoryTranslated!= null)
            {
                // disassociate existing relationship
                _categoryTranslated._InternalCategoryTranslated.Remove(this);
            }

            _categoryTranslated= value;

            if (value != null)
            {
                //make the association
                _categoryTranslated._InternalCategoryTranslated.Add(this);
            }
        }
    }
    private CategoryTranslated _categoryTranslated;
Berryl
thank you for the replay.at the row .Access.CamelCaseField(CamelCasePrefix.Underscore)i have this error:CamelCasePrefix is not assignable to parameter type FluentNhibernate.mapping.Prefix
Andrea
i tried this: .Access.CamelCaseField(FluentNHibernate.Mapping.Prefix.Underscore)i used your same property name : _InternalCategoriesTranslatedBut when i look at the collection with debug i have the same error.
Andrea
you'd should post your hbms too, for people without patience to wait for the non-premium download (like moi!). The _Internal stuff is for the domain to construct the collection lazily AND give the other side of your bi-directional relation (ie, the CategoryTranslated) a way to hook in there, but NOT the mapping. See my edited answer. You should probably post the error too
Berryl
@Andrea / Mark: My bad, that access code was lifted from a FNH convention I use; in the class map just change it to ".Access.LowerCaseField(Prefix.Underscore)" and it will work. Cheers
Berryl