Using one session per request, how to handle updating child objects

generale

New Member
I'm having some serious issues with Fluent Nhibernate in my ASP.NET WebForms app when trying to modify a child object and then saving the parent object.My solution is currently made of 2 projects :
  • Core : A class library where all entities & repositories classes are located
  • Website : The ASP.NET 4.5 WebForms application
Here is my simple mapping for my Employee object:\[code\]public class EmployeeMap : ClassMap<Employee>{ public EmployeeMap() { Id(x => x.Id).GeneratedBy.Identity(); Map(x => x.DateCreated); Map(x => x.Username); Map(x => x.FirstName); Map(x => x.LastName); HasMany(x => x.TimeEntries).Inverse().Cascade.All().KeyColumn("Employee_id"); }}\[/code\]Here is my my mapping for the TimeEntry object:\[code\]public class TimeEntryMap : ClassMap<TimeEntry>{ public TimeEntryMap() { Id(x => x.Id).GeneratedBy.Identity(); Map(x => x.DateCreated); Map(x => x.Date); Map(x => x.Length); References(x => x.Employee).Column("Employee_id").Not.Nullable(); }}\[/code\]As stated in the title, i'm using one session per request in my web app, using this code in Gobal.asax:\[code\] public static ISessionFactory SessionFactory = Core.SessionFactoryManager.CreateSessionFactory(); public static ISession CurrentSession { get { return (ISession)HttpContext.Current.Items["current.session"]; } set { HttpContext.Current.Items["current.session"] = value; } } protected Global() { BeginRequest += delegate { System.Diagnostics.Debug.WriteLine("New Session"); CurrentSession = SessionFactory.OpenSession(); }; EndRequest += delegate { if (CurrentSession != null) CurrentSession.Dispose(); }; } \[/code\]Also, here is my SessionFactoryManager class:\[code\]public class SessionFactoryManager{ public static ISession CurrentSession; public static ISessionFactory CreateSessionFactory() { return Fluently.Configure() .Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c.FromConnectionStringWithKey("Website.Properties.Settings.WebSiteConnString"))) .Mappings(m => m .FluentMappings.AddFromAssembly(Assembly.GetExecutingAssembly())) .ExposeConfiguration(cfg => new SchemaUpdate(cfg).Execute(false, true)) .BuildSessionFactory(); } public static ISession GetSession() { return (ISession)HttpContext.Current.Items["current.session"]; }}\[/code\]Here is one of my repository class, the one i use to handle the Employee's object data operations:\[code\]public class EmployeeRepository<T> : IRepository<T> where T : Employee{ private readonly ISession _session; public EmployeeRepository(ISession session) { _session = session; } public T GetById(int id) { T result = null; using (ITransaction tx = _session.BeginTransaction()) { result = _session.Get<T>(id); tx.Commit(); } return result; } public IList<T> GetAll() { IList<T> result = null; using (ITransaction tx = _session.BeginTransaction()) { result = _session.Query<T>().ToList(); tx.Commit(); } return result; } public bool Save(T item) { var result = false; using (ITransaction tx = _session.BeginTransaction()) { _session.SaveOrUpdate(item); tx.Commit(); result = true; } return result; } public bool Delete(T item) { var result = false; using (ITransaction tx = _session.BeginTransaction()) { _session.Delete(_session.Load(typeof (T), item.Id)); tx.Commit(); result = true; } return result; } public int Count() { var result = 0; using (ITransaction tx = _session.BeginTransaction()) { result = _session.Query<T>().Count(); tx.Commit(); } return result; }}\[/code\]Now, here is my problem. When i'm trying to insert Employee(s), everything is fine. Updating is also perfect... well, as long as i'm not updating one of the TimeEntry object referenced in the "TimeEntries" property of Employee...Here is where an exception is raised (in a ASPX file of the web project):\[code\] var emp = new Employee(1); foreach (var timeEntry in emp.TimeEntries) { timeEntry.Length += 1; } emp.Save();\[/code\]Here is the exception that is raised:[NonUniqueObjectException: a different object with the same identifier value was already associated with the session: 1, of entity: Core.Entities.Employee]Basically, whenever I try to A) Load an employee and B) Modify one of it's saved TimeEntry, I get that exception.FYI, I tried replacing the "SaveOrUpdate()" in the repository for "Merge()". It did an excellent job, but when creating an object using Merge(), my object never gets it's Id set.I also tried creating and flushing the ISession in each function of my repository. It made no sense because as soon as i was trying to load the TimeEntries property of an Employee, an exception was raised, saying the object could not be lazy-loaded as the ISession was closed...I'm at lost and would appreciate some help. Any suggestion for my repository is also welcome, as i'm quite new to this.Thanks you guys!
 
Back
Top