C# – Fluent NHibernate AutoMapping, supposed to save time but this has me pulling the hair out

c++fluent-nhibernatenhibernateorm

I'm new to NHibernate and FNH as well. I'm familiar with ORM's and decided to see what all the buzz was about with this particular one mostly because of the productivity gains. At this point I think my time would have been better spent using something else but I don't want to let this defeat me and I'm hoping it's a stupid error I'm making because I want so badly for this to impress me. Anyway, I tried manually mapping the entities (Fluent) to no avail and am now trying to use the automap feature. Here is my domain model.

public class Book
{
 public virtual int Id { get; protected set; }
 public virtual string Isbn { get; set; }
 public virtual string Title { get; set; }
 public virtual string Author { get; set; }
 public virtual string Publisher { get; set; }
 public virtual User Seller { get; set; }
 public virtual ICollection<string> Pics {get; private set;}
 public virtual string Condition { get; set; }
 public virtual decimal Price { get; set; }
 public virtual ExchangeMethod PreferedExchangeMethod { get; set; }
}
public class Course
{
 public virtual int Id { get; protected set; }
 public virtual University University { get; set; }
 public virtual Semester Semester { get; set; }
 public virtual string Description { get; set; }
 public virtual string Name { get; set; }
 public virtual ICollection<Book> RequiredBooks { get; private set; }
}
public class Exchange
{
 public virtual int Id { get; protected set; }
 public virtual User Buyer { get; set; }
        public virtual User Seller { get; set; }
        public virtual Book Book { get; set; }
        public virtual ExchangeMethod Method { get; set; }
        public virtual decimal Price { get; set; }
        public virtual int SellerFeedbackRating { get; set; }
        public virtual int BuyerFeedbackRating{get; set;}
        public virtual string SellerComment { get; set; }
        public virtual string BuyerComment { get; set; }
}
public class Semester
{
        public virtual int id { get; protected set; }
        public virtual University University { get; set; }
        public virtual int Year { get; set; }
        public virtual string Term { get; set; }
}
public class University
{
        public virtual string Name { get; set; }
        public virtual int Connections { get; set; }
        public virtual ICollection<Course> Courses { get; private set; }
}
public class User
{
        public virtual string UserName { get; set; }
        public virtual string FirstName { get; set; }
        public virtual string LastName { get; set; }
        public virtual string Email { get; set; }
        public virtual ICollection<Course> Enrollment { get; private set; }
        public virtual ICollection<Book> Library { get; private set; }
        public virtual ICollection<Exchange> Exchanges { get; private set; }
}

And here is my mapping

public static ISessionFactory CreateSessionFactory()
{
 IPersistenceConfigurer persistenceConfigurer = SQLiteConfiguration.Standard.UsingFile(DbFile);
        return Fluently.Configure()
                .Database(persistenceConfigurer)
                .Mappings(m => m.AutoMappings.Add(
                    AutoMap.AssemblyOf<User>(assem => assem.Namespace == "DataTransferObjects")
                        .Override<User>(map => map.Id(user => user.UserName))
                        .Override<University>(map => map.Id(univ => univ.Name))
                    ))
                .ExposeConfiguration(BuildSchema)
                .BuildSessionFactory();
}
private static void BuildSchema(Configuration config)
{
 // delete the existing db on each run
        if (File.Exists(DbFile))
           File.Delete(DbFile);
        // this NHibernate tool takes a configuration (with mapping info in)
        // and exports a database schema from it
        new SchemaExport(config).Create(false, true);
}

This is the error I keep getting which is pretty vague:
XML validation error: The element 'class' in namespace 'urn:nhibernate-mapping-2.2' has invalid child element 'property' in namespace 'urn:nhibernate-mapping-2.2'. List of possible elements expected: 'meta, subselect, cache, synchronize, comment, tuplizer, id, composite-id' in namespace 'urn:nhibernate-mapping-2.2'

Thanks for any help and sorry for the long post.

EDIT
Does the way I layed out my model leave me prone to errors with circular logic e.g. User has a book and the book has a user? I would expect the automapping to be able to pick that up.

Best Solution

Are you using the latest version of FNH and NHibernate 2.1 RTM?

I am not so sure about your Overrides of the Id code. Have you tried without this and having an Id in each table?

Here is how I do my mappings with Automap. I tell it what Assembly to pull from, what Namespace in particular and then I give it the BaseTypes that my entities derive from. I use the ConventionDiscovery to change some of the foreign key naming conventions and set up cascading and inverse properties, etc.

PersistenceModel = AutoPersistenceModel
        .MapEntitiesFromAssemblyOf<>()
        .Where(type => type.Namespace != null && type.Namespace.Contains("Model"))
        .WithSetup(s =>
                     {
                       s.IsBaseType = type => type ==  typeof (DateTimeBase)
                                              || type == typeof (SimpleBase);
                     })
        .ConventionDiscovery.AddFromAssemblyOf();
Then I add the persistence model to the automappings. I use the ExportTo method to get a copy of the generated xml files - looking at the xml helps to diagnose some problems.

.Mappings(m => m.AutoMappings
                         .Add(persistenceModel)
                         .ExportTo(@"../../ExportAutoMaps"));

AutoMapping has worked great for me - though it did take time to learn and experiment.
I am using jet database and I have to explicitly create my database file for NHibernate to run the schema on. I am unfamiliar with how sqlLite works.