views:

184

answers:

1

I've searched around for a solution as best I can, but it seems I'm at a loss somewhere. This is my first dive into Fluent NHibernate & NHibernate.

The short version (which will still be long) is that I have a database that has tables User, Role, UserRoles. The relationship b/t them should be fairly intuitive...A user can be assigned multiple roles. The UserRoles table stores these associations so User & Role don't link directly.I think I need a many-to-many relationship here, but I'm not sure how to map that in NFLuent.

I've done the example on the NFLuent getting started page and have it working. I've tried to surmise the answers from it, but I've missed something somewhere.

I will list my entity & mappings in a second, but the error I'm getting is:

An invalid or incomplete configuration was used while creating a SessionFactory. Check PotentialReasons collection, and InnerException for more detail.

The Potential reasons collection doesn't say anything but the InnerException says:

{"Could not determine type for: DataAccess.Entities.User, DataAccess, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null, for columns: NHibernate.Mapping.Column(User)"}

The hbm file Here are my entities:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DataAccess.Entities
{
public class User
    {
        public virtual int Id { get; private set; }
        public virtual string DisplayName { get; set; }
        public virtual string Email { get; set; }
        public virtual string Password { get; set; }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DataAccess.Entities
{
    public class Role
    {
        public virtual int Id { get; private set; }
        public virtual string RoleName { get; set; }
        public virtual string RoleDescription { get; set; }  
    }
}   

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DataAccess.Entities
{
    public class UserRole 
    {
         public virtual int Id { get; private set; } 
         public virtual Role Role { get; set; }
         public virtual User User { get; set; }

         //Attempted variations
         //public virtual IList<Role> Roles{ get; set; }
         //public virtual IList<User> Users { get; set; }

         //public UserRole()
         //{
         //    Roles = new List<Role>();
         //    Users = new List<User>();
         //}

         //public virtual void AddRole(Role role)
         //{
         //    Roles.Add(role);
         //}

         //public virtual void AddUser(User user)
         //{
         //    Users.Add(user);
         //}
    }
}

Here are my mappings:

using DataAccess.Entities;
using FluentNHibernate.Mapping;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DataAccess.Mappings
{
    public class RoleMap : ClassMap<Role>
    {
        public RoleMap()
        {
            Id(x => x.Id);
            Map(x => x.RoleDescription);
            Map(x => x.RoleName);
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DataAccess.Entities;
using FluentNHibernate.Mapping;

namespace DataAccess.Mappings
{
    public class UserMap : ClassMap<User>
    {
        public UserMap()
        {
            Id(x => x.Id);
            Map(x => x.DisplayName);
            Map(x => x.Email);
            Map(x => x.Password);
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DataAccess.Entities;
using FluentNHibernate.Mapping;

namespace DataAccess.Mappings
{
    public class UserRoleMap : ClassMap<UserRole>
    {
        public UserRoleMap()
        {
            Id(x => x.Id);
            Map(x => x.User);
            Map(x => x.Role);            
            //HasMany(x => x.Users)
            //  .Inverse()
            //  .Cascade.All();
            //HasMany(x => x.Roles)
            //  .Inverse()
            //  .Cascade.All();
        }
    }
}

private static ISessionFactory CreateSessionFactory()
{
    return Fluently.Configure()
          .Database(MsSqlConfiguration.MsSql2005
            .ConnectionString(c => c
                .Server(@".\SQLEXPRESS")
                .Database("MyDB")
                .TrustedConnection())
            )                                                     
          .Mappings(m => m
            .FluentMappings.AddFromAssembly(Assembly.GetExecutingAssembly())
            .ExportTo(@"C:\Development\MVC\DataAccess\hbms"))
            .ExposeConfiguration((Configuration config) => new SchemaExport(config).Create(false, true))
          .BuildSessionFactory();
}   

Any suggestions would be appreciated. Thanks!

A: 

Your scenario is analogous to the linking of Store and Products in the example given in the Getting started with Fluent NHibernate.

UserRoles is just a linking mechanism so you are better off not thinking of it as an entity. Instead, you have a User that has been assigned Roles and/or a Role that has been assigned to Users.

So you might have:

public class User
{
    public virtual int Id { get; private set; }
    public virtual string DisplayName { get; set; }
    public virtual string Email { get; set; }
    public virtual string Password { get; set; }
    public virtual IList<Role> Roles { get; set; }

    public User()
    {
        Roles = new List<Role>();
    }

    public AddToRole(Role role)
    {
        role.Users.Add(this);
        Roles.Add(role);
    }
}

public class Role
{
    public virtual int Id { get; private set; }
    public virtual string RoleName { get; set; }
    public virtual string RoleDescription { get; set; }
    public virtual IList<User> Users { get; set; }

    public Role()
    {
        Users = new List<User>();
    }
}

public class UserMap : ClassMap<User>
{
    public UserMap()
    {
        Id(x => x.Id);
        Map(x => x.DisplayName);
        Map(x => x.Email);
        Map(x => x.Password);
        HasManyToMany(x => x.Roles)
          .Table("UserRoles");
    }
}

public class RoleMap : ClassMap<Role>
{
    public RoleMap()
    {
        Id(x => x.Id);
        Map(x => x.RoleDescription);
        Map(x => x.RoleName);
        HasManyToMany(x => x.Users)
          .Inverse()
          .Table("UserRoles");
    }
}
Ajw
Jason