Fluent nHibernate: Unsupported mapping type
Asked Answered
B

1

11

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
Bullington answered 3/1, 2012 at 18:7 Comment(9)
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.Bullington
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.Bullington
When does the exception occur? Please post the full exception! Exception.ToString()Chequered
Is this your only class? Maybe you are referencing it from another one and using Map instead of References.Indonesian
@ColeW I have put the stack trace in the main body of the questionBullington
@DiegoMijelshon I have other classes but have used this as an example. I have tried connecting to these other classes but they give the same errors. I do not have the admin class referenced from any of the other classes.Bullington
Do any of your mappings work? Can you comment out the .Mappings(m => m.FluentMappings.Add<Admin>()) to see if the next one works? Also it's much easier to use something like this instead: m.FluentMappings.AddFromAssemblyOf<OrderMap>()Chequered
@ColeW That's helped a lot. I changed the mapping to use .Mappings(m => m.FluentMappings.AddFromAssemblyOf<Admin>()) and the code runs however the nested classes are not available (will have to do some more work on my mapping files.) Strange how when the entities are called individually they fail.Bullington
@ColeW and to answer your other question - no none of them work if called from the .Add<T> method.Bullington
F
12

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();
Finsen answered 4/1, 2012 at 16:52 Comment(1)
better approach will be inherit all Maps to some interface say IMap and use .Mappings(m => m.FluentMappings.AddFromAssemblyOf<NameSpace.IMap>())Fish

© 2022 - 2024 — McMap. All rights reserved.