views:

713

answers:

2

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.

+2  A: 

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.

Maggie
Thanks for replying. I'm not sure the exact version #, but I pulled it down directly from the SVN repo yesterday so it's the latest version. I think a lot of the methods you use in your example are now obsolete. I don't want to have an integer ID when it makes more sense for me to use a string that I want to be unique anyway, I'll give it a try though and it may help narrow it down for me.
Marcus King
I added an expicit "Id" property as you suggested and am still getting the same error. I've got to be missing something easy.
Marcus King
+1  A: 

Well, as I thought it was a stupid error. For the Semester Entity I had "id" instead of "Id". Kind of disapointing that FNH is case sensitive when doing the automapping, I would have thought otherwise with the "strong typing" support they have to prevent typos in config files.

FYI, When doing automapping it by default tries to map to a property called "Id" on each of your entities unless you specify other wise.

Marcus King