fluentnhibernate configuration Error - fluent-nhibernate

I have created one console application by watching videos from http://www.d80.co.uk/post/2011/10/06/NHibernate-Video-Tutorial.aspx website. when i tried to executing the code its giving me following error:
An invalid or incomplete configuration was used while creating a SessionFactory. Check PotentialReasons collection, and InnerException for more detail.
but when i have downloaded the code and executed, its working fine. i have checked both the code and are same. so not under stand what i am doing wrong. i am posting my code here please help me to get out of this situation.
NhibernateHelper.cs
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate;
using NHibernate.Tool.hbm2ddl;
using System;
namespace FluentNHibernate
{
class NhibernateHelper
{
private static ISessionFactory _sessionFactory;
private static ISessionFactory sessionFactory
{
get
{
if (_sessionFactory == null)
{
initialisationFactory();
}
return _sessionFactory;
}
}
private static void initialisationFactory()
{
try
{
_sessionFactory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2005.ConnectionString(#"Server=10.10.10.7;Database=TestDatabase;uid=sa;pwd=9ijnhy6;Trusted_Connection=false;").ShowSql())
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<Car>())
.ExposeConfiguration(cfg => new SchemaExport(cfg).Create(true, true))
.BuildSessionFactory();
}
catch (Exception e)
{
throw;
}
}
public static ISession OpenSession()
{
return sessionFactory.OpenSession();
}
}
}
Program.cs
using System;
using FluentNHibernate.Mapping;
namespace FluentNHibernate
{
internal class Program
{
public static void Main(string[] args)
{
using (var session = NhibernateHelper.OpenSession())
{
using (var transaction = session.BeginTransaction())
{
var fordMake = new Make
{
Name = "Ford"
};
var fiestaModel = new Model
{
Name = "Fiesta",
Make = fordMake
};
var car = new Car
{
Make = fordMake,
Model = fiestaModel,
Title = "Dans Car"
};
session.Save(car);
transaction.Commit();
Console.WriteLine("Created Car " + car.Title);
}
}
Console.ReadLine();
}
}
public class MakeMap : ClassMap<Make>
{
public MakeMap()
{
Id(x => x.Id);
Map(x => x.Name);
}
}
public class ModelMap : ClassMap<Model>
{
public ModelMap()
{
Id(x => x.Id);
Map(x => x.Name);
References(x => x.Make).Cascade.All();
}
}
public class CarMap : ClassMap<Car>
{
public CarMap()
{
Id(x => x.Id).GeneratedBy.HiLo("Car");
Map(x => x.Title);
References(x => x.Make).Cascade.All();
References(x => x.Model).Cascade.All();
}
}
public class Make
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
}
public class Model
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual Make Make { get; set; }
}
public class Car
{
public virtual int Id { get; set; }
public virtual string Title { get; set; }
public virtual Make Make { get; set; }
public virtual Model Model { get; set; }
}
}

Your NHibernateHelper.cs is considerably different than mine.
Try changing
_sessionFactory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2005.ConnectionString(#"Server=10.10.10.7;Database=TestDatabase;uid=sa;pwd=9ijnhy6;Trusted_Connection=false;").ShowSql())
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<Car>())
.ExposeConfiguration(cfg => new SchemaExport(cfg).Create(true, true))
.BuildSessionFactory();
To:
_sessionFactory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2005.ConnectionString(c => c.FromConnectionStringWithKey("ConnectionString")))
.Mappings(cfg =>
{
cfg.FluentMappings.AddFromAssembly(Assembly.GetExecutingAssembly());
cfg.FluentMappings.Conventions.Add(AutoImport.Never());
})
.ExposeConfiguration(x =>
{
x.SetProperty("current_session_context_class", mode);
})
.BuildSessionFactory();
In Your web.config or app.config add the following within tags:
<connectionStrings>
<add name="ConnectionString" connectionString="Data Source=10.10.10.7; Initial Catalog=TestDatabase; User Id=sa; Password=9ijnhy6;"/>
</connectionStrings
Hopefully this helps.

Related

Nhibernate QueryOver does not work but CreateSqlQuery works

In my project I have a class named User with the following definition:
public class User
{
public virtual Guid UserId { get; set; }
public virtual string UserName { get; set; }
public virtual string Password { get; set; }
}
and here is mapper class:
public class UserMap : ClassMap<User>
{
public UserMap()
{
Id(x => x.UserId).Column("UserId");
Map(x => x.UserName).Column("UserName");
Map(x => x.Password).Column("Password");
}
}
when I try to execute the following code it does not return any result:
public IQueryable<User> GetByUserPassword(string userName, string password)
{
var result = Session.QueryOver<User>()
.Where(x => x.Password == password && x.UserName == userName)
.List<User>();
return result.AsQueryable();
}
But when I use CreateSqlQuery("select * from [dbo].[User]") method it returns value without column names:
and here is my Nhibernate configuration code:
public class NHibernateSessionFactory
{
private ISessionFactory sessionFactory;
private readonly string ConnectionString = "";
public NHibernateSessionFactory(String connectionString)
{
this.ConnectionString = connectionString;
}
public ISessionFactory SessionFactory
{
get { return sessionFactory ?? (sessionFactory = CreateSessionFactory()); }
}
public ISessionFactory CreateSessionFactory()
{
try
{
return Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(x => x.FromConnectionStringWithKey(ConnectionString)))
.Mappings(m =>
m.FluentMappings
.AddFromAssemblyOf<User>())
.ExposeConfiguration(config => new SchemaUpdate(config).Execute(false, true))
.BuildSessionFactory();
}
catch (Exception ex)
{
throw ex;
}
}
}
what is the problem?
Do not use QueryOver, use just Query:
var result = Session.Query<User>()
.Where(x => x.Password == password && x.UserName == userName);
//already IQueryable<User>
This was helpful but my mistake was a mistake in adding MapClass Assembly which was in other assembly:
.AddFromAssemblyOf()

Nhibernate Remove child collection without having property in the parent object

Suppose I have the following model
public class Customer
{
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
}
public class ActivityLog
{
public virtual Guid Id { get; set; }
public virtual Guid CustomerId { get; set; }
public virtual Customer Customer { get; set; }
public virtual DateTime ActivityDate { get; set; }
}
I would like to be able to remove customer and all corresponding ActivityLog items, by calling
session.Delete(customer);
What I don't want to is to have a property
List<ActivityLog> Logs in my Customer class. Is it possible to achieve in Nhibernate? I have tried EF, and it works there, but in HN getting reference constraint exception.
My mappings:
public class CustomerMap : ClassMapping<Customer>
{
public CustomerMap()
{
Id(x => x.Id, map => map.Generator(Generators.GuidComb));
Property(x => x.Name);
}
}
public class ActivityLogMap : ClassMapping<ActivityLog>
{
public ActivityLogMap()
{
Id(x => x.Id, map => map.Generator(Generators.GuidComb));
Property(x => x.ActivityDate);
ManyToOne(x => x.Customer, mapping =>
{
mapping.Class(typeof(Customer));
mapping.Column("CustomerId");
});
}
}
Maybe possible to have some extension hook and inspect mapping and do it manually for Nhibernate?
Edit: Here how it works with EF
public class CustomerEFMap : EntityTypeConfiguration<Customer>
{
public CustomerEFMap()
{
ToTable("Customer");
HasKey(x => x.Id);
Property(x => x.Name);
}
}
public class ActivityLogEFMap : EntityTypeConfiguration<ActivityLog>
{
public ActivityLogEFMap()
{
ToTable("ActivityLog");
HasKey(x => x.Id);
HasRequired(x => x.Customer).WithMany().HasForeignKey(x => x.CustomerId);
}
}
using (var context = new ObjectContext())
{
var customer = context.Set<Customer>().Find(id);
context.Set<Customer>().Remove(customer);
context.SaveChanges();
}
Having Customer and corresponding ActivityLog in DB, removes both
I would like to be able to remove customer and all corresponding
ActivityLog items, by calling
session.Delete(customer);
What I don't want to is to have a property List Logs in
my Customer class. Is it possible to achieve in Nhibernate?
NO. Impossible, not intended, not supported. NHibernate is ORM tool and will/can care about relations. Without relations, no care (no cascading)
But, we can always hide that List Property by making it protected
public class Customer
{
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
// HIDDEN in fact from consumers, managed by NHibernate
protected virtual IList<ActivitLog> { get; set; }
}
and the mapping with cascade in place - will do what is required.
As Radim Köhler states, I don't think there's any simple way to map the behaviour of a cascade without actually having the relationship. But as your reason for this is a plugin-based architecture, making use of a partial class might be what you need.
You can include the collection of ActivityLogs as a protected collection as part of a partial class in the plugin DLL. If your mapping then maps the collection, deleting the Customer will delete the ActivityLogs.
The following example should work - note that I'm using FluentNhibernate for the mapping.
This solution does rely on you be able to mark the Customer class as partial.
using FluentAssertions;
using FluentNHibernate;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using FluentNHibernate.Mapping;
using NHibernate.Linq;
using NHibernate.Tool.hbm2ddl;
using NUnit.Framework;
using System;
using System.Collections.Generic;
namespace MapTest
{
public partial class Customer
{
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
}
public class ActivityLog
{
public virtual Guid Id { get; set; }
public virtual Customer Customer { get; set; }
public virtual DateTime ActivityDate { get; set; }
}
public class CustomerMap : ClassMap<Customer>
{
public CustomerMap()
{
Id(x => x.Id).GeneratedBy.Guid();
Map(x => x.Name);
HasMany<ActivityLog>(Reveal.Member<Customer>("ActivityLogs")).Cascade.All();
}
}
public class ActivityLogMap : ClassMap<ActivityLog>
{
public ActivityLogMap()
{
Id(x => x.Id).GeneratedBy.Guid();
Map(x => x.ActivityDate);
References(x => x.Customer);
}
}
// Part of your plugin DLL
public partial class Customer
{
protected virtual IList<ActivityLog> ActivityLogs { get; set; }
}
[TestFixture]
public class PartialClassCascade
{
[Test]
public void RunOnceToSetupDb()
{
Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2012.ConnectionString(#"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=MapTest;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<CustomerMap>())
.ExposeConfiguration(cfg => new SchemaUpdate(cfg).Execute(false, true))
.BuildSessionFactory();
}
[Test]
public void DeletingCustomerWithActivityLogs()
{
var sessionFactory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2012.ConnectionString(#"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=MapTest;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<CustomerMap>())
.BuildSessionFactory();
using (var session = sessionFactory.OpenSession())
using (var tx = session.BeginTransaction())
{
session.CreateQuery("delete ActivityLog a").ExecuteUpdate();
session.CreateQuery("delete Customer c").ExecuteUpdate();
tx.Commit();
}
var homerId = default(Guid);
using (var session = sessionFactory.OpenSession())
using (var tx = session.BeginTransaction())
{
var homer = new Customer
{
Name = "Homer Simpson"
};
var monty = new Customer
{
Name = "Monty Burns"
};
session.Save(homer);
session.Save(monty);
homerId = homer.Id;
var activityLog1 = new ActivityLog
{
Customer = homer,
ActivityDate = DateTime.Now,
};
var activityLog2 = new ActivityLog
{
Customer = monty,
ActivityDate = DateTime.Now.AddDays(1),
};
session.Save(activityLog1);
session.Save(activityLog2);
tx.Commit();
}
using (var session = sessionFactory.OpenSession())
using (var tx = session.BeginTransaction())
{
var customer = session.Get<Customer>(homerId);
session.Delete(customer);
tx.Commit();
}
using (var session = sessionFactory.OpenSession())
using (var tx = session.BeginTransaction())
{
var customers = session.Query<Customer>();
var activityLogs = session.Query<ActivityLog>();
customers.Should().HaveCount(1);
activityLogs.Should().HaveCount(1);
}
}
}
}

After updating to nHibernate 4, cannot use ManyToMany Mappings. Could not determine type

After updating to nHibernate (4.0.2.4000 via nuget), the many to many mappings that previously worked now cause mapping exception "Could not determine type for: nHibernateManyToMany.IRole, nHibernateManyToMany, for columns: NHibernate.Mapping.Column(id)"
Seems to be only for many to many, and when the List is a interface (i.e. List<Role> vs List<IRole>).
Example code that now fails:
class Program
{
static void Main(string[] args)
{
var configuration = new Configuration().SetProperty(Environment.ReleaseConnections, "on_close")
.SetProperty(Environment.Dialect, typeof(SQLiteDialect).AssemblyQualifiedName)
.SetProperty(Environment.ConnectionDriver, typeof(SQLite20Driver).AssemblyQualifiedName)
.SetProperty(Environment.CollectionTypeFactoryClass, typeof(DefaultCollectionTypeFactory).AssemblyQualifiedName)
.SetProperty(Environment.CommandTimeout, "0");
var mapper = new ModelMapper();
mapper.AddMappings(new[] { typeof(EmployeeMapping), typeof(RoleMapping) });
var hbmMapping = mapper.CompileMappingForAllExplicitlyAddedEntities();
hbmMapping.autoimport = false;
configuration.AddMapping(hbmMapping);
// this line will fail
var factory = configuration.BuildSessionFactory();
}
}
public class Employee
{
public virtual int Id { get; set; }
public virtual List<IRole> Roles { get; set; }
}
public interface IRole
{
int Id { get; set; }
string Description { get; set; }
}
public class Role : IRole
{
public virtual int Id { get; set; }
public virtual string Description { get; set; }
}
public class EmployeeMapping : ClassMapping<Employee>
{
public EmployeeMapping()
{
Id(c => c.Id, x =>
{
x.Type(NHibernateUtil.Int32);
x.Generator(Generators.Identity);
x.Column("EmployeeId");
});
Bag(x => x.Roles, m =>
{
m.Table("EmployeeRole");
m.Key(km =>
{
km.Column("EmployeeId");
km.NotNullable(true);
km.ForeignKey("FK_Role_Employee");
});
m.Lazy(CollectionLazy.Lazy);
}, er => er.ManyToMany(m =>
{
m.Class(typeof(Role));
m.Column("RoleId");
}));
}
}
public class RoleMapping : ClassMapping<Role>
{
public RoleMapping()
{
Id(c => c.Id, x =>
{
x.Type(NHibernateUtil.Int32);
x.Generator(Generators.Identity);
x.Column("RoleId");
});
Property(x => x.Description, c =>
{
c.Length(50);
c.NotNullable(true);
});
}
}
Any help or suggestions about where we could look for details on how this has changed since v3 would be appreciated.
Turned out to be a bug in nHibernate.
A pull request has been submitted here https://github.com/nhibernate/nhibernate-core/pull/385

The specified table does not exist

I'm try to use fluent nhibernate but my nunit test it failing with a The error
CookBook.Tests.FluentCategoryTests.CanCorrectlyMapCategory:
System.Data.SqlServerCe.SqlCeException : The specified table does not exist. [ Category ]
this is my Category object
public class Category
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
}
and here is the test
[TestFixture]
class FluentCategoryTests
{
private ISessionFactory _sessionFactory;
private RecipeConfiguration configuration = new RecipeConfiguration();
[TestFixtureSetUp]
public void TestSetup()
{
var cfg = new RecipeConfiguration();
_sessionFactory = Fluently.Configure()
.Database(MsSqlCeConfiguration.Standard.ShowSql().ConnectionString("Data Source=CookBook.sdf"))
.Mappings(m => m.AutoMappings.Add(AutoMap.AssemblyOf<Category>(cfg)))
.BuildSessionFactory();
}
[Test]
public void CanCorrectlyMapCategory()
{
using (ISession session = _sessionFactory.OpenSession())
{
new PersistenceSpecification<Category>(session)
.CheckProperty(c => c.Id, 1)
.CheckProperty(c => c.Name, "Dessert")
.VerifyTheMappings();
}
}
}
So what am I doing wrong?
to answer the question in your comment:
using NHibernate.Tool.hbm2ddl;
...
var cfg = new RecipeConfiguration();
_sessionFactory = Fluently.Configure()
.Database(MsSqlCeConfiguration.Standard.ShowSql().ConnectionString("Data Source=CookBook.sdf"))
.Mappings(m => m.AutoMappings.Add(AutoMap.AssemblyOf<Category>(cfg)))
.ExposeConfiguration(config => new SchemaExport(config).Execute(false, true, false))
.BuildSessionFactory();

NHibernate query is not returning any results

I'm trying to get Fluent and NHibernate configured properly with ASP.NET MVC. As far as I know it's configured properly but when I access the page that uses this setup I am not receiving any data results.
The model I'm using is called Brand and the database table is Brands.
Here is a snippet from my BrandController:
public ActionResult Index()
{
IRepository<Brand> repo = new BrandRepository();
var brands = repo.GetAll().ToList<Brand>();
return View(brands);
}
Here is a snippet from my BrandRepository:
ICollection<Brand> IRepository<Brand>.GetAll()
{
using (ISession session = NHibernateHelper.OpenSession())
{
var brands = session
.CreateCriteria(typeof(Brand))
.List<Brand>();
return brands;
}
}
Here is my NHibernateHelper:
public class NHibernateHelper
{
private static ISessionFactory _sessionFactory;
private static ISessionFactory SessionFactory
{
get
{
if (_sessionFactory == null)
{
_sessionFactory = Fluently.Configure()
.Database(
MsSqlConfiguration.MsSql2008
.ConnectionString(c => c
.FromConnectionStringWithKey("ShoesFullAccess")
)
)
.BuildSessionFactory();
}
return _sessionFactory;
}
}
public static ISession OpenSession()
{
return SessionFactory.OpenSession();
}
}
Here is my Brand model:
public class Brand
{
public int Id { get; private set; }
public virtual string Name { get; set; }
public virtual IList<Style> Styles { get; private set; }
public Brand()
{
Styles = new List<Style>();
}
public virtual void AddStyle(Style style)
{
Styles.Add(style);
}
}
And finally, here is my BrandMap:
public class BrandMap : ClassMap<Brand>
{
public BrandMap()
{
Id(x => x.Id);
Map(x => x.Name);
HasMany(x => x.Styles)
.Inverse()
.Cascade.All();
}
}
If anyone could point me in the right direction for how I can narrow down the problem I would very grateful!
You are not adding the mappings to the configuration.
Add this before .BuildSessionFactory():
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<BrandMap>())
I needed to make a few modifications to my code. The first and main one was adding the mappings to the configuration as Diego pointed out.
You are not adding the mappings to the configuration.
Add this before .BuildSessionFactory():
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<BrandMap>())
The next thing I had to fix was my Brand model. I needed to make the Id field virtual.
And finally, I needed to change my BrandMap just a little bit -- I had to specify exactly which table it was pointing to by adding this code Table("Brands");