2

I have a simple class with a IList<string> property. How to map this property in Fluent Nhibernate ?

[Serializable]
public class ExportTask
{
    private IList<string> _csvExportList = new List<string>();

    public ExportTask()
    {}

    public virtual IList<string> CsvExportList
    {
        get { return _csvExportList; }
        set { _csvExportList = value; }
    }
}

public class ExportTaskMap : SubclassMap<ExportTask>
{
    public ExportTaskMap()
    {           
        HasMany(x => x.CsvExportList)
               .Element("CsvExportList")
               .Cascade
               .AllDeleteOrphan();
    }
}

Following error occurs:

Initializing -failed to lazily initialize a collection of role: MyApp.Tasks.ExportTask.CsvExportList, no session or session was closed

When calling addrange on the collection:

var exportList = new List<string>()
                     {
                        {"item1"},
                        {"item2"}
                      };

CsvExportList.AddRange(exportList);
jero2rome
  • 1,548
  • 1
  • 21
  • 39

2 Answers2

6

It truns out we can use AsList mapping with a column for the list index and allworks great. I wonder why there are no answers out there for this simple usecase. Hope it helps out someone.

public class ExportTaskMap : SubclassMap<ExportTask>
{
  public ExportTaskMap()
  {           
     HasMany(x => x.CsvExportList)
           .Element(@"CsvProperty")
           .KeyColumn(@"ExportTask_id")
           .Table(@"CsvExportProperties")
           .AsList(x => x.Column(@"CsvPropertyListIndex"))
           .Not.LazyLoad();
  }
}

And the mapped table will look like the following in the database.

enter image description here

jero2rome
  • 1,548
  • 1
  • 21
  • 39
  • This doesn't work with an IList but only with IList, any idea why? The index column is always null. – Rafi Dec 26 '14 at 11:22
  • You cannot use this style of mapping to map a list of objects. There are other ways to do it. – jero2rome Apr 15 '15 at 10:22
0

Would be helpful to see the error you get, but one thing seems to be obvious: you are missing setter of the IList<string> CsvExportList. So, mapping should target the field

HasMany<string>(Reveal.Property<string>("_csvExportList"))

Check these how to handle field mapping:

Or change your IList<string> to have at least protected setter (I personally would go this way) and remove the readonly setting.

private IList<string> _csvExportList;
public virtual IList<string> CsvExportList
{
    get { return _csvExportList ?? (_csvExportList = new List<string>(); }
    protected set { _csvExportList = value; }
}

These are hints, the exception or error you get could tell us more

Community
  • 1
  • 1
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • Added additional error message. HasMany(Reveal.Property("_csvExportList")) couldn't be used since the syntax results in error. Also, couldn't have a setter since, readonly fields cannot have setter. I use Add() and AddRange() methods to fill the collection. – jero2rome Sep 24 '14 at 14:43
  • Honestly... I did not see the readonly. Why is it there? This does not make sense to me, it only brings you issues. If you want to hide the CsvExportList to any upper layer, hide its setter (make it protected). That's enough. And the error you get is related to fact, that you are working with the entity ExportTask once the session is closed. You have to extend the lifetime of that session or eagerly load that collection... BUT I would go with protected setter for sure... – Radim Köhler Sep 24 '14 at 14:48