Nhibernate Remove child collection without having property in the parent object - nhibernate

Suppose I have the following model
public class Customer
{
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
}
public class ActivityLog
{
public virtual Guid Id { get; set; }
public virtual Guid CustomerId { get; set; }
public virtual Customer Customer { get; set; }
public virtual DateTime ActivityDate { get; set; }
}
I would like to be able to remove customer and all corresponding ActivityLog items, by calling
session.Delete(customer);
What I don't want to is to have a property
List<ActivityLog> Logs in my Customer class. Is it possible to achieve in Nhibernate? I have tried EF, and it works there, but in HN getting reference constraint exception.
My mappings:
public class CustomerMap : ClassMapping<Customer>
{
public CustomerMap()
{
Id(x => x.Id, map => map.Generator(Generators.GuidComb));
Property(x => x.Name);
}
}
public class ActivityLogMap : ClassMapping<ActivityLog>
{
public ActivityLogMap()
{
Id(x => x.Id, map => map.Generator(Generators.GuidComb));
Property(x => x.ActivityDate);
ManyToOne(x => x.Customer, mapping =>
{
mapping.Class(typeof(Customer));
mapping.Column("CustomerId");
});
}
}
Maybe possible to have some extension hook and inspect mapping and do it manually for Nhibernate?
Edit: Here how it works with EF
public class CustomerEFMap : EntityTypeConfiguration<Customer>
{
public CustomerEFMap()
{
ToTable("Customer");
HasKey(x => x.Id);
Property(x => x.Name);
}
}
public class ActivityLogEFMap : EntityTypeConfiguration<ActivityLog>
{
public ActivityLogEFMap()
{
ToTable("ActivityLog");
HasKey(x => x.Id);
HasRequired(x => x.Customer).WithMany().HasForeignKey(x => x.CustomerId);
}
}
using (var context = new ObjectContext())
{
var customer = context.Set<Customer>().Find(id);
context.Set<Customer>().Remove(customer);
context.SaveChanges();
}
Having Customer and corresponding ActivityLog in DB, removes both

I would like to be able to remove customer and all corresponding
ActivityLog items, by calling
session.Delete(customer);
What I don't want to is to have a property List Logs in
my Customer class. Is it possible to achieve in Nhibernate?
NO. Impossible, not intended, not supported. NHibernate is ORM tool and will/can care about relations. Without relations, no care (no cascading)
But, we can always hide that List Property by making it protected
public class Customer
{
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
// HIDDEN in fact from consumers, managed by NHibernate
protected virtual IList<ActivitLog> { get; set; }
}
and the mapping with cascade in place - will do what is required.

As Radim Köhler states, I don't think there's any simple way to map the behaviour of a cascade without actually having the relationship. But as your reason for this is a plugin-based architecture, making use of a partial class might be what you need.
You can include the collection of ActivityLogs as a protected collection as part of a partial class in the plugin DLL. If your mapping then maps the collection, deleting the Customer will delete the ActivityLogs.
The following example should work - note that I'm using FluentNhibernate for the mapping.
This solution does rely on you be able to mark the Customer class as partial.
using FluentAssertions;
using FluentNHibernate;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using FluentNHibernate.Mapping;
using NHibernate.Linq;
using NHibernate.Tool.hbm2ddl;
using NUnit.Framework;
using System;
using System.Collections.Generic;
namespace MapTest
{
public partial class Customer
{
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
}
public class ActivityLog
{
public virtual Guid Id { get; set; }
public virtual Customer Customer { get; set; }
public virtual DateTime ActivityDate { get; set; }
}
public class CustomerMap : ClassMap<Customer>
{
public CustomerMap()
{
Id(x => x.Id).GeneratedBy.Guid();
Map(x => x.Name);
HasMany<ActivityLog>(Reveal.Member<Customer>("ActivityLogs")).Cascade.All();
}
}
public class ActivityLogMap : ClassMap<ActivityLog>
{
public ActivityLogMap()
{
Id(x => x.Id).GeneratedBy.Guid();
Map(x => x.ActivityDate);
References(x => x.Customer);
}
}
// Part of your plugin DLL
public partial class Customer
{
protected virtual IList<ActivityLog> ActivityLogs { get; set; }
}
[TestFixture]
public class PartialClassCascade
{
[Test]
public void RunOnceToSetupDb()
{
Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2012.ConnectionString(#"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=MapTest;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<CustomerMap>())
.ExposeConfiguration(cfg => new SchemaUpdate(cfg).Execute(false, true))
.BuildSessionFactory();
}
[Test]
public void DeletingCustomerWithActivityLogs()
{
var sessionFactory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2012.ConnectionString(#"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=MapTest;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<CustomerMap>())
.BuildSessionFactory();
using (var session = sessionFactory.OpenSession())
using (var tx = session.BeginTransaction())
{
session.CreateQuery("delete ActivityLog a").ExecuteUpdate();
session.CreateQuery("delete Customer c").ExecuteUpdate();
tx.Commit();
}
var homerId = default(Guid);
using (var session = sessionFactory.OpenSession())
using (var tx = session.BeginTransaction())
{
var homer = new Customer
{
Name = "Homer Simpson"
};
var monty = new Customer
{
Name = "Monty Burns"
};
session.Save(homer);
session.Save(monty);
homerId = homer.Id;
var activityLog1 = new ActivityLog
{
Customer = homer,
ActivityDate = DateTime.Now,
};
var activityLog2 = new ActivityLog
{
Customer = monty,
ActivityDate = DateTime.Now.AddDays(1),
};
session.Save(activityLog1);
session.Save(activityLog2);
tx.Commit();
}
using (var session = sessionFactory.OpenSession())
using (var tx = session.BeginTransaction())
{
var customer = session.Get<Customer>(homerId);
session.Delete(customer);
tx.Commit();
}
using (var session = sessionFactory.OpenSession())
using (var tx = session.BeginTransaction())
{
var customers = session.Query<Customer>();
var activityLogs = session.Query<ActivityLog>();
customers.Should().HaveCount(1);
activityLogs.Should().HaveCount(1);
}
}
}
}

Related

How to get records in first table(projects) not present in second table(finances) with foreign key reference using nhibernate

I'm trying to query on a simple data structure in nhibernate and MSSQL
dbo.Projects : Id(int, not null)
dbo.Finances : Id(int, not null), ProjectId(int,not null), foreign key references to dbo.projects
I want to get all the records in projects table that are not present in finances table where the finances table has a foreign key reference ProjectId.
I am migrating to (Fluent) Nhibernate 3 from EntityFramework?
//So far I have got here:
public IQueryable<ProjectModel> GetProjectsNotPresentInFinance()
{
var factory = Fluently.Configure()
.Database(MsSqlConfiguration
.MsSql2008
.ConnectionString(m_connectionString))
.Mappings(m => m.FluentMappings
.AddFromAssemblyOf<ProjectMap>()
).BuildSessionFactory();
using (var session = factory.OpenSession())
{
var allprojects = session.QueryOver<ProjectModel>();
var projectsToReturn = allprojects.List<ProjectModel>().AsQueryable();
//--- Something like : all the records not in finances table ---------
// .Where( proj => !db.Finances.Where(fin => fin.ProjectId == proj.Id).Any())
// .Select(project => new ProjectModel
// {
// Id=project.Id,
// ProjectName = project.ProjectName,
// });
return projectsToReturn;
}
}
public class FinanceModel
{
public virtual int Id { get; set; }
public virtual int ProjectId { get; set; }
}
public class ProjectModel
{
public virtual int Id { get; set; }
public virtual string ProjectName { get; set; }
}
public class ProjectMap:ClassMap<ProjectModel>
{
public ProjectMap() {
Table("Projects");
Id(x => x.Id);
Map(x => x.ProjectName);
}
}
public class FinanceMap : ClassMap<FinanceModel>
{
public FinanceMap()
{
Table("Finances");
Id(x => x.Id);
References(x => x.ProjectModel);
}
}
//-------------------------------------------------------
//This is an Equivalent working code Using EntityFramework :
public IQueryable<ProjectModel> GetProjectsNotPresentInFinance() {
IQueryable<ProjectModel> projectList = db.Projects
.Where( proj => !db.Finances.Where(fin => fin.ProjectId == proj.Id).Any())
.Select(project => new ProjectModel
{
Id=project.Id,
ProjectName = project.ProjectName,
});
return projectList;
}
//-------------------------------------------------------
On second thought, you may try this without changing anything to your mapping, using a subquery :
var notOrphanProjectIdsSubquery = QueryOver.Of<FinanceModel>()
.Select(x => x.ProjectId);
var orphanProjects = session.QueryOver<ProjectModel>()
.WithSubquery
.WhereProperty(x=>x.Id)
.NotIn(notOrphanProjectIdsSubquery)
.List();
----------------------- Initial answer
Assuming you have a mapped Finances Property in your Project class, and according to https://stackoverflow.com/a/14980450/1236044, it should be something like :
var orphanProjects = session.QueryOver<ProjectModel>()
.WhereRestrictionOn(x => x.Finances).IsEmpty()
.List();
I must confess I am not proficient with FluentNH. I guess the classes and mappings should be something like this, hoping I'm not setting you on the wrong track...
public class FinanceModel
{
public virtual int Id { get; set; }
public virtual int ProjectId { get; set; }
public virtual ProjectModel Project{get;set;}
}
public class ProjectModel
{
public virtual int Id { get; set; }
public virtual string ProjectName { get; set; }
public virtual IList<FinanceModel> Finances { get; set; }
}
public class ProjectMap:ClassMap<ProjectModel>
{
public ProjectMap() {
Table("Projects");
Id(x => x.Id);
Map(x => x.ProjectName);
HasMany(x => x.Finances);
}
}
public class FinanceMap : ClassMap<FinanceModel>
{
public FinanceMap()
{
Table("Finances");
Id(x => x.Id);
References(x => x.Project);
}
}

fluentnhibernate configuration Error

I have created one console application by watching videos from http://www.d80.co.uk/post/2011/10/06/NHibernate-Video-Tutorial.aspx website. when i tried to executing the code its giving me following error:
An invalid or incomplete configuration was used while creating a SessionFactory. Check PotentialReasons collection, and InnerException for more detail.
but when i have downloaded the code and executed, its working fine. i have checked both the code and are same. so not under stand what i am doing wrong. i am posting my code here please help me to get out of this situation.
NhibernateHelper.cs
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate;
using NHibernate.Tool.hbm2ddl;
using System;
namespace FluentNHibernate
{
class NhibernateHelper
{
private static ISessionFactory _sessionFactory;
private static ISessionFactory sessionFactory
{
get
{
if (_sessionFactory == null)
{
initialisationFactory();
}
return _sessionFactory;
}
}
private static void initialisationFactory()
{
try
{
_sessionFactory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2005.ConnectionString(#"Server=10.10.10.7;Database=TestDatabase;uid=sa;pwd=9ijnhy6;Trusted_Connection=false;").ShowSql())
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<Car>())
.ExposeConfiguration(cfg => new SchemaExport(cfg).Create(true, true))
.BuildSessionFactory();
}
catch (Exception e)
{
throw;
}
}
public static ISession OpenSession()
{
return sessionFactory.OpenSession();
}
}
}
Program.cs
using System;
using FluentNHibernate.Mapping;
namespace FluentNHibernate
{
internal class Program
{
public static void Main(string[] args)
{
using (var session = NhibernateHelper.OpenSession())
{
using (var transaction = session.BeginTransaction())
{
var fordMake = new Make
{
Name = "Ford"
};
var fiestaModel = new Model
{
Name = "Fiesta",
Make = fordMake
};
var car = new Car
{
Make = fordMake,
Model = fiestaModel,
Title = "Dans Car"
};
session.Save(car);
transaction.Commit();
Console.WriteLine("Created Car " + car.Title);
}
}
Console.ReadLine();
}
}
public class MakeMap : ClassMap<Make>
{
public MakeMap()
{
Id(x => x.Id);
Map(x => x.Name);
}
}
public class ModelMap : ClassMap<Model>
{
public ModelMap()
{
Id(x => x.Id);
Map(x => x.Name);
References(x => x.Make).Cascade.All();
}
}
public class CarMap : ClassMap<Car>
{
public CarMap()
{
Id(x => x.Id).GeneratedBy.HiLo("Car");
Map(x => x.Title);
References(x => x.Make).Cascade.All();
References(x => x.Model).Cascade.All();
}
}
public class Make
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
}
public class Model
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual Make Make { get; set; }
}
public class Car
{
public virtual int Id { get; set; }
public virtual string Title { get; set; }
public virtual Make Make { get; set; }
public virtual Model Model { get; set; }
}
}
Your NHibernateHelper.cs is considerably different than mine.
Try changing
_sessionFactory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2005.ConnectionString(#"Server=10.10.10.7;Database=TestDatabase;uid=sa;pwd=9ijnhy6;Trusted_Connection=false;").ShowSql())
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<Car>())
.ExposeConfiguration(cfg => new SchemaExport(cfg).Create(true, true))
.BuildSessionFactory();
To:
_sessionFactory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2005.ConnectionString(c => c.FromConnectionStringWithKey("ConnectionString")))
.Mappings(cfg =>
{
cfg.FluentMappings.AddFromAssembly(Assembly.GetExecutingAssembly());
cfg.FluentMappings.Conventions.Add(AutoImport.Never());
})
.ExposeConfiguration(x =>
{
x.SetProperty("current_session_context_class", mode);
})
.BuildSessionFactory();
In Your web.config or app.config add the following within tags:
<connectionStrings>
<add name="ConnectionString" connectionString="Data Source=10.10.10.7; Initial Catalog=TestDatabase; User Id=sa; Password=9ijnhy6;"/>
</connectionStrings
Hopefully this helps.

Fluent Nhibernate - HQL select problem

I am new to NHibernate.
I am using Fluent Nhibernate and when I run a simple query I get null results.
Here is my configuration:
Fluent Configuration:
Fluently.Configure().Database(MsSqlConfiguration.MsSql2008
.ShowSql()
.ConnectionString(c => c
.FromConnectionStringWithKey("MY_DB")))
.Mappings(m =>m.FluentMappings.AddFromAssemblyOf<CsrDAL.Mappings.CsrRegistrationMap>())
.BuildSessionFactory();
Entity Class
public class Industry
{
public virtual int Id { get; private set; }
public virtual string Name { get; set; }
public virtual IList<CsrRegistration> ReferencedRegistrations { get; set; }
}
Map Class
public class IndustryMap : ClassMap<Industry>
{
public IndustryMap()
{
Table("industries");
Id(x => x.Id. "id");
Map(x => x.Name, "name");
}
}
Repository Fetch Method
public static IList<Industry> getData(CsrRegistration registration)
{
using (var session = CsrDalHelper.OpenSession())
{
using (var transaction = session.BeginTransaction())
{
try
{
IQuery q = session.CreateQuery("from Industry ind where ind.Id=1");
IList<Industry> inds =
q.List<Industry>();
return inds; // <-- This is null
}
}
}
}
Thank you in advance!
Dimitris
The problem was in session management, somewhere else in my code.
I was wrongly adding collection items to an entity outside the NH session.
As a newcomer to nhibernate, I am now studying the docs in more details.
Thank you

Fluent NHibernate mapping IDictionary<string, class> in a smart way

Given these classes:
using System.Collections.Generic;
namespace FluentMappingsQuestion
{
public class Entity
{
public virtual int Id { get; set; }
public virtual IDictionary<string, Property> Properties { get; set; }
}
public class Property
{
public virtual Entity OwningEntity { get; set; }
public virtual string Name { get; set; }
public virtual int Value { get; set; }
public virtual decimal OtherValue { get; set; }
}
}
How can I map them using NHibernate (preferably fluent flavor) so that doing this is possible:
[Test]
public void EntityPropertyMappingTest()
{
using (var session = _factory.OpenSession())
{
var entity = new Entity();
// (#1) I would *really* like to use this
entity.Properties["foo"] = new Property { Value = 42, OtherValue = 42.0M };
session.Save(entity);
session.Flush();
// (#2) I would like the entity below to "update itself"
// on .Save or .Flush. I got it to work with .Load()
Assert.AreEqual(42, entity.Properties["foo"].Value);
Assert.AreEqual(42.0M, entity.Properties["foo"].OtherValue);
Assert.AreEqual("foo", entity.Properties["foo"].Name);
Assert.AreEqual(entity, entity.Properties["foo"].Owner);
}
}
I have almost managed to do this with these mappings:
// class EntityMap : ClassMap<Entity>
public EntityMap()
{
Id(x => x.Id);
HasMany(x => x.Properties)
.Cascade.AllDeleteOrphan()
.KeyColumn("EntityId")
.AsMap(x => x.Name);
}
// class PropertyMap : ClassMap<Property>
public PropertyMap()
{
Id(x => x.Id);
References(x => x.OwningEntity).Column("EntityId");
Map(x => x.Name).Length(32);
Map(x => x.Value);
{
The problems I have:
If I make Entity.Properties .Inverse(), it starts breaking
If I don't make it .Inverse() then NHibernate does: INSERT(Entity), INSERT(Property), UPDATE(Property) instead of just INSERT(Entity), INSERT(Property)
If I make Property.Name .Not.Nullable(), it starts breaking
If I don't make it .Not.Nullable(), I have a hole in my db schema
How should I change my mappings?
I worked around this by specifying this mapping:
HasMany<Property>(Reveal.Member<Entity>("InternalProperties"))
.AsMap(p => p.Name)
.Cascade.AllDeleteOrphan()
.Inverse();
and creating two properties of type IDictionary<string, Property>: Properties and InternalProperties. The first one is a proxy dictionary over the second one, and deals with setting the OwningEntity and Name properties for the Property entries.

Many to Many relationship with Fluent NHibernate

I'm getting the following error: "Can't figure out what the other side of a many-to-many should be."
Team Entity:
public class Team : IEntity
{
public int Id { get; set; }
public string Name { get; set; }
public IList<Employee> Employee { get; set; }
public Team()
{
Employee = new List<Employee>();
}
}
Employee Entity:
public class Employee : IEntity
{
public int Id { get; set; }
public String LastName { get; set; }
public string FirstName { get; set; }
public IList<Team> Team { get; set; }
public string EMail { get; set; }
public Employee()
{
Team = new List<Team>();
}
}
Team mapping:
public class TeamMap : ClassMap<Team>
{
public TeamMap()
{
// identity mapping
Id(p => p.Id);
// column mapping
Map(p => p.Name);
// relationship mapping
HasManyToMany<Employee>(m => m.Employee);
}
}
Employee mapping:
public class EmployeeMap : ClassMap<Employee>
{
public EmployeeMap()
{
// identifier mapping
Id(p => p.Id);
// column mapping
Map(p => p.EMail);
Map(p => p.LastName);
Map(p => p.FirstName);
// relationship mapping
HasManyToMany<Team>(m => m.Team);
}
}
Nobody has an answer?
Edit: The error occurs on the following code:
public static ISessionFactory CreateSessionFactory()
{
return Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008
.ConnectionString(c=>
c.Database("Ariha")
.TrustedConnection()
.Server("localhost")
).ShowSql())
.Mappings(m => m.FluentMappings
.AddFromAssemblyOf<BookMap>()
.AddFromAssemblyOf<MagazineMap>()
.AddFromAssemblyOf<EmployeeMap>()
.AddFromAssemblyOf<TeamMap>())
.ExposeConfiguration(BuildSchema)
.BuildSessionFactory();
}
edit: here the whole solution: http://rapidshare.com/files/309653409/S.O.L.I.D.Ariha.rar.html
Could you provide code that causes your error? I just tried your mappings and they seem to work fine (on fluent 1.0 RTM and NH 2.1.1 GA with an SQLite database), with a minor modification to your EmployeeMap (I have assumed the employee-team relationship is bidirectional, and as per documentation you need to mark one side as inverse).
// relationship mapping
HasManyToMany<Team>(m => m.Team).Inverse();
Of course if the employee-team relationship is not bidirectional, I would have thought you should be able to specify a different .Table(name) for each one - but I have not tested this and you seem to be getting different results anyway (hence why providing example code would be best)
I'd also add that I suspect Set semantics (instead of Bag) would be more appropriate for the Employee.Team and Team.Employee properties. (Irregardless, don't do anything that assumes order is preserved, there is no guarantee that it will be)
Suggested mapping and example:
public class Team
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Employee> Employee { get; set; }
public Team() { Employee = new List<Employee>(); }
}
public class Employee
{
public int Id { get; set; }
public String LastName { get; set; }
public string FirstName { get; set; }
public ICollection<Team> Team { get; set; }
public string EMail { get; set; }
public Employee() { Team = new List<Team>(); }
}
public class TeamMap : ClassMap<Team>
{
public TeamMap()
{
Not.LazyLoad();
// identity mapping
Id(p => p.Id);
// column mapping
Map(p => p.Name);
// relationship mapping
HasManyToMany<Employee>(m => m.Employee).AsSet();
}
}
public class EmployeeMap : ClassMap<Employee>
{
public EmployeeMap()
{
Not.LazyLoad();
// identifier mapping
Id(p => p.Id);
// column mapping
Map(p => p.EMail);
Map(p => p.LastName);
Map(p => p.FirstName);
// relationship mapping
HasManyToMany<Team>(m => m.Team).Inverse().AsSet();
}
}
[TestFixture]
public class Mapping
{
[Test]
public void PersistDepersist()
{
var fcfg = Fluently.Configure()
.Database(SQLiteConfiguration.Standard.UsingFile("testdb.sqldb"))
.Mappings(mc =>
{
mc.FluentMappings.Add(typeof (TeamMap));
mc.FluentMappings.Add(typeof (EmployeeMap));
})
.ExposeConfiguration(cfg => new SchemaExport(cfg).Execute(false, true, false));
var sess = fcfg.BuildSessionFactory().OpenSession();
var teams = Enumerable.Range(0, 4).Select(i => new Team() {Name = "Team " + i}).ToArray();
var employees = Enumerable.Range(0, 10).Select(i => new Employee() {FirstName = "Employee " + i}).ToArray();
teams[0].Employee = new List<Employee>() {employees[0], employees[3], employees[5]};
teams[1].Employee = new List<Employee>() {employees[7], employees[2], employees[5]};
teams[3].Employee = new List<Employee>() {employees[0], employees[8], employees[9]};
foreach (var team in teams)
foreach (var employee in team.Employee)
employee.Team.Add(team);
Console.WriteLine("Dumping Generated Team/Employees:");
Dump(teams);
Dump(employees);
using (var t = sess.BeginTransaction())
{
foreach (var team in teams)
sess.Save(team);
foreach (var employee in employees)
sess.Save(employee);
t.Commit();
}
sess.Flush();
sess.Clear();
var teamsPersisted = sess.CreateCriteria(typeof (Team)).List<Team>();
var employeesPersisted = sess.CreateCriteria(typeof (Employee)).List<Employee>();
Assert.AreNotSame(teams, teamsPersisted);
Assert.AreNotSame(employees, employeesPersisted);
Console.WriteLine();
Console.WriteLine();
Console.WriteLine("Dumping Depersisted Team/Employees:");
Dump(teamsPersisted);
Dump(employeesPersisted);
}
private static void Dump(IEnumerable<Team> teams)
{
foreach (var team in teams)
Console.WriteLine("Team: " + team.Name + " has members: " + string.Join(", ", team.Employee.Select(e => e.FirstName).ToArray()));
}
private static void Dump(IEnumerable<Employee> employees)
{
foreach (var employee in employees)
Console.WriteLine("Employee: " + employee.FirstName + " in teams: " + string.Join(", ", employee.Team.Select(e => e.Name).ToArray()));
}
}
Fluent NHibernate tries to determine what the other side of a many-to-many relationship is by looking at the entity names and the collection properties. I believe it's not working in your case because your collection properties aren't plural; try renaming your collections Employees and Teams respectively.
Another way is to manually set the many-to-many table name on both sides, as this will disable the prediction.