English 中文(简体)
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.





相关问题
Does Fluent NHibernate support "trigger-identity"

I posted the question in the Fluent-NHibernate newgroup but so far there has been no answer from the void. Is there a Fluent NHibernate mapping for the NHibernate "trigger-identity" method of ...

automapping nested components naming conventions

Im making the switch from Fluent Mapping to Automapping in my current project. If I have the following domain: public class Matter{ public Client Client{get;set;} } public class Client { ...

NHibernate Search in a List using ICriteria

I have my class X : public class ClassX { public virtual IList<ClassY> ListY { get; set; } ... } My ClassX mapping (using Fluent) ... HasMany<ClassX>(x => x.ListY ) ....

Fluent nHibernate keeps recreating my database, why?

I m trying to convert my data layer from Linq2Sql to nHibernate. I think Xml the configuration in nHibernate is pretty backwards so I m using Fluent. I ve managed to get fluent, add in a repository ...

How to fluent-map this (using fluent nhibernate)?

I have two tables in my database "Styles" and "BannedStyles". They have a reference via the ItemNo. Now styles can be banned per store. So if style x is banned at store Y then its very possible that ...

热门标签