1

I've run into a truly frustrating problem and spent several hours trying every which way to sort out. When a collection is lazy loaded on some objects it throws a LazyInitializationException stating there is no session or the session is closed. After taking out the code into a clean console app for testing - I'm convinced the session simply cannot be closed! Here is the code:

    private static ISessionFactory _sessionFactory;

    static void Main(string[] args)
    {
        _sessionFactory = BuildFactory(@"*<ThisIsMyConnectionString>*");
        using (var session = _sessionFactory.OpenSession())
        {
            var allContacts = session.Query<Contact>().Where(x=>x.EmployeeId.HasValue);
            foreach (var contact in allContacts)
            {
                var allServices = contact.EmployeeServices.ToArray();
            }
            session.Dispose();
        }
    }

    private static ISessionFactory BuildFactory(string connectionString = null)
    {
        return Fluently.Configure()
                       .Database(FluentNHibernate.Cfg.Db.MsSqlConfiguration.MsSql2008.ConnectionString(connectionString))
                       .Mappings(m =>
                           {
                               m.FluentMappings.Conventions.AddFromAssemblyOf<TableNameConvention>();
                               m.FluentMappings.AddFromAssemblyOf<KioskAdapterConfigMapping>();
                           })
                       .BuildConfiguration().BuildSessionFactory();
    }

And here is my (fluent) mappings:

public ServiceMapping()
    {
        Table("tblServices");
        Id(x => x.Id, "ServiceId");
        Map(x => x.Name);
    }
public ContactMapping()
     {
         Table("tblContacts");
         Id(x => x.Id, "ContactId");
         Map(x => x.EmployeeId);
         HasManyToMany(x => x.EmployeeServices)
             .Table("lnkEmployeeService")
             .ParentKeyColumn("EmployeeId")
             .PropertyRef("EmployeeId")
             .ChildKeyColumn("ServiceId")
             .NotFound.Ignore();
     }

How on earth is the session closed? Some database records do not have any records in the "lnkEmployeeService" table, but all foreign keys are in place and valid. Also the link table does have extra columns and is actually a composite key with other columns, but I don't care about rest of the data.

2 Answers 2

1

The problem is hidden in the fact, that the EmployeeServices collection is mapped to the Contact by the not-unique value "EmployeeId".

Other words, let's assume three contacts

ContactId, EmployeeId
1        , 1
2        , 2
3        , 2

Now, we instruct NHibernate be ready, to load 3 collections. They will/should/must be unique, for each of the contacts. So in the ISession, they could be kept by their unique identifier. In case of NOT property-ref mapping they would be like:

CollectionId - Collection
1            - the first collection of all Services related to contact with ID 1 
2            - the first collection of all Services related to contact with ID 2 
3            - the first collection of all Services related to contact with ID 3

But we do have a problem here, because our unique identifier for our collections is

CollectionId - Collection
1            ...
2            ...
2            - here we go... this (collection) or the previous 
               must now be removed from a session... 
               no way how to load/handle it any more

The key, must be unique, that's the point, even if this is the property-ref. On a bit different place of the documentation, we can see 5.1.10. many-to-one:

The property-ref attribute should only be used for mapping legacy data where a foreign key refers to a unique key of the associated table other than the primary key.

While this is not explained for <bag> mapping the logic is still the same

Sign up to request clarification or add additional context in comments.

Comments

0

I think the problem is that you're calling Dispose on an IDisposable that's wrapped in a using block. The using block is the equivalent of writing

var myDisposable = new SomeIDisposableImplementation();
try { ... }
finally 
{ 
    if(myDisposable != null) myDisposable.Dispose(); 
}

In your code Dispose is called twice. My guess is that's causing the problem but I wasn't able to duplicate the exception in a simple test.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.