11
votes

I'm setting up a new solution to map against SQL data that has been imported from an Access database. Auto Mappings work fine against the entities I have defined but I need to be able to use the Fluent mapping type to give access to the .NotFound.Ignore extension.

I have used exactly the same syntax in another project (I think!) which works fine. Have I made a schoolboy error to cause the "Unsupported mapping type 'IT.Classes.Entities.Admin'"? Any help is much appreciated.

DDL:

CREATE TABLE [dbo].[Admin](
    [ID] [int] NOT NULL,
    [primaryEmail] [nvarchar](50) NULL,
    [secondaryEmail] [nvarchar](50) NULL,
    [highPriorityEmail] [nvarchar](50) NULL,
    [MobileEmail] [nvarchar](50) NULL,
    [EmailUser] [bit] NOT NULL,
    [HelpDeskMessage] [nvarchar](max) NULL
) ON [PRIMARY]

Entity:

namespace IT.Classes.Entities
{
    public class Admin
    {
    public virtual bool EmailUser { get; set; }

    public virtual string HelpdeskMessage { get; set; }

    public virtual string HighPriorityEmail { get; set; }

    public virtual int Id { get; set; }

    public virtual string MobileEmail { get; set; }

    public virtual string PrimaryEmail { get; set; }

    public virtual string SecondaryEmail { get; set; }
    }
}

Mapping:

using FluentNHibernate.Mapping; using IT.Classes.Entities;

namespace IT.Classes.Mappings
{
    public sealed class AdminMap : ClassMap<Admin>
    {
        public AdminMap()
        {
            this.Id(x => x.Id);
            this.Map(x => x.EmailUser);
            this.Map(x => x.HelpdeskMessage);
            this.Map(x => x.HighPriorityEmail);
            this.Map(x => x.MobileEmail);
            this.Map(x => x.PrimaryEmail);
            this.Map(x => x.SecondaryEmail);
        }
    }
}

Session Factory:

private static ISessionFactory CreateItHelpdeskSessionFactory()
{
    return
        Fluently.Configure().Database(
            MsSqlConfiguration.MsSql2008.ConnectionString(
                ConfigurationManager.ConnectionStrings["ITHelpdesk"].ConnectionString))
                .Mappings(m => m.FluentMappings.Add<Admin>())
                .Mappings(m => m.FluentMappings.Add<Applications>())
                .Mappings(m => m.FluentMappings.Add<Category>())
                .Mappings(m => m.FluentMappings.Add<Log>())
                .Mappings(m => m.FluentMappings.Add<Multipliers>())
                .Mappings(m => m.FluentMappings.Add<Os>())
                .Mappings(m => m.FluentMappings.Add<Priority>())
                .Mappings(m => m.FluentMappings.Add<Request>())
                .Mappings(m => m.FluentMappings.Add<Status>())
                .BuildSessionFactory();
}

EDIT

I thought I would export the auto mappings to see if they would highlight a problem in my fluent mappings but they seem to be correct:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class xmlns="urn:nhibernate-mapping-2.2" name="IT.Classes.Entities.Admin, ITClasses, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="`Admin`">
    <id name="Id" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <column name="Id" />
      <generator class="identity" />
    </id>
    <property name="EmailUser" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <column name="EmailUser" />
    </property>
    <property name="HelpdeskMessage" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <column name="HelpdeskMessage" />
    </property>
    <property name="HighPriorityEmail" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <column name="HighPriorityEmail" />
    </property>
    <property name="MobileEmail" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <column name="MobileEmail" />
    </property>
    <property name="PrimaryEmail" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <column name="PrimaryEmail" />
    </property>
    <property name="SecondaryEmail" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <column name="SecondaryEmail" />
    </property>
  </class>
</hibernate-mapping>

EDIT 2

Full stack trace. Note potentialreasons = 0.

FluentNHibernate.Cfg.FluentConfigurationException: An invalid or incomplete configuration was used while creating a SessionFactory. Check PotentialReasons collection, and InnerException for more detail.
 ---> FluentNHibernate.Cfg.FluentConfigurationException: An invalid or incomplete configuration was used while creating a SessionFactory. Check PotentialReasons collection, and InnerException for more detail.

 ---> System.InvalidOperationException: Unsupported mapping type 'IT.Classes.Entities.Admin'
   at FluentNHibernate.PersistenceModel.Add(Type type) in d:\Builds\FluentNH\src\FluentNHibernate\PersistenceModel.cs:line 152
   at FluentNHibernate.Cfg.FluentMappingsContainer.Apply(PersistenceModel model) in d:\Builds\FluentNH\src\FluentNHibernate\Cfg\FluentMappingsContainer.cs:line 127
   at FluentNHibernate.Cfg.MappingConfiguration.Apply(Configuration cfg) in d:\Builds\FluentNH\src\FluentNHibernate\Cfg\MappingConfiguration.cs:line 84
   at FluentNHibernate.Cfg.FluentConfiguration.BuildConfiguration() in d:\Builds\FluentNH\src\FluentNHibernate\Cfg\FluentConfiguration.cs:line 252
   --- End of inner exception stack trace ---
   at FluentNHibernate.Cfg.FluentConfiguration.BuildConfiguration() in d:\Builds\FluentNH\src\FluentNHibernate\Cfg\FluentConfiguration.cs:line 264
   at FluentNHibernate.Cfg.FluentConfiguration.BuildSessionFactory() in d:\Builds\FluentNH\src\FluentNHibernate\Cfg\FluentConfiguration.cs:line 230
   --- End of inner exception stack trace ---
   at FluentNHibernate.Cfg.FluentConfiguration.BuildSessionFactory() in d:\Builds\FluentNH\src\FluentNHibernate\Cfg\FluentConfiguration.cs:line 235
   at ConsoleChecker.Program.CreateItHelpdeskSessionFactory() in E:\code\code_testing\2010\ASPHelpdesks\ConsoleChecker\Program.cs:line 48
   at ConsoleChecker.Program.GetRequests() in E:\code\code_testing\2010\ASPHelpdesks\ConsoleChecker\Program.cs:line 40
   at ConsoleChecker.Program.Main(String[] args) in E:\code\code_testing\2010\ASPHelpdesks\ConsoleChecker\Program.cs:line 24
1
I had a thought that the lack of primary key on the table may be causing the problem so I set the Id column as PK but still the same error.Rowan
Further thought - created a blank database and used the schema generation tool to attempt to create the tables automatically and rule out any issues with the database itself. This still fails with the same error.Rowan
When does the exception occur? Please post the full exception! Exception.ToString()Cole W
Is this your only class? Maybe you are referencing it from another one and using Map instead of References.Diego Mijelshon
@ColeW I have put the stack trace in the main body of the questionRowan

1 Answers

12
votes

In your configuration code, the types mentioned in the Fluent Mappings should be the map classes, not the classes being mapped.

That is, instead of:

return
    Fluently.Configure().Database(
        MsSqlConfiguration.MsSql2008.ConnectionString(
            ConfigurationManager.ConnectionStrings["ITHelpdesk"].ConnectionString))
            .Mappings(m => m.FluentMappings.Add<Admin>())
            .Mappings(m => m.FluentMappings.Add<Applications>())
            .Mappings(m => m.FluentMappings.Add<Category>())
            .Mappings(m => m.FluentMappings.Add<Log>())
            .Mappings(m => m.FluentMappings.Add<Multipliers>())
            .Mappings(m => m.FluentMappings.Add<Os>())
            .Mappings(m => m.FluentMappings.Add<Priority>())
            .Mappings(m => m.FluentMappings.Add<Request>())
            .Mappings(m => m.FluentMappings.Add<Status>())
            .BuildSessionFactory();

You need to say:

return
    Fluently.Configure().Database(
        MsSqlConfiguration.MsSql2008.ConnectionString(
            ConfigurationManager.ConnectionStrings["ITHelpdesk"].ConnectionString))
            .Mappings(m => m.FluentMappings.Add<AdminMap>())
            .Mappings(m => m.FluentMappings.Add<ApplicationsMap>())
            .Mappings(m => m.FluentMappings.Add<CategoryMap>())
            .Mappings(m => m.FluentMappings.Add<LogMap>())
            .Mappings(m => m.FluentMappings.Add<MultipliersMap>())
            .Mappings(m => m.FluentMappings.Add<OsMap>())
            .Mappings(m => m.FluentMappings.Add<PriorityMap>())
            .Mappings(m => m.FluentMappings.Add<RequestMap>())
            .Mappings(m => m.FluentMappings.Add<StatusMap>())
            .BuildSessionFactory();

Even better, to avoid having a separate line for every class map, use the .AddFromAssemblyOf<>() method, which uses reflection to add all class maps from a given assembly:

return
    Fluently.Configure().Database(
        MsSqlConfiguration.MsSql2008.ConnectionString(
            ConfigurationManager.ConnectionStrings["ITHelpdesk"].ConnectionString))
            .Mappings(m => m.FluentMappings.AddFromAssemblyOf<AdminMap>())
            .BuildSessionFactory();