private static void CreateSampleData(ISession session)
        {
            using (var transaction = session.BeginTransaction())
            {
                // create a couple of Stores each with some Products and Employees
                var barginBasin = new Store { Name = "Bargin Basin" };
                var superMart = new Store { Name = "SuperMart" };

                var potatoes = new Product { Name = "Potatoes", Price = 3.60 };
                var fish = new Product { Name = "Fish", Price = 4.49 };
                var milk = new Product { Name = "Milk", Price = 0.79 };
                var bread = new Product { Name = "Bread", Price = 1.29 };
                var cheese = new Product { Name = "Cheese", Price = 2.10 };
                var waffles = new Product { Name = "Waffles", Price = 2.41 };

                var daisy = new Employee { FirstName = "Daisy", LastName = "Harrison" };
                var jack = new Employee { FirstName = "Jack", LastName = "Torrance" };
                var sue = new Employee { FirstName = "Sue", LastName = "Walkters" };
                var bill = new Employee { FirstName = "Bill", LastName = "Taft" };
                var joan = new Employee { FirstName = "Joan", LastName = "Pope" };

                // add products to the stores, there's some crossover in the products in each
                // store, because the store-product relationship is many-to-many
                AddProductsToStore(barginBasin, potatoes, fish, milk, bread, cheese);
                AddProductsToStore(superMart, bread, cheese, waffles);

                // add employees to the stores, this relationship is a one-to-many, so one
                // employee can only work at one store at a time
                AddEmployeesToStore(barginBasin, daisy, jack, sue);
                AddEmployeesToStore(superMart, bill, joan);

                // save both stores, this saves everything else via cascading
                session.SaveOrUpdate(barginBasin);
                session.SaveOrUpdate(superMart);

                transaction.Commit();
            }
        }
 public virtual void AddEmployee(Employee employee)
 {
     employee.Store = this;
     Staff.Add(employee);
 }
        static void Main(string[] args)
        {
            bool bCreateOrUpdateSchema = true;
            bool bCreateSampleData = false || bCreateOrUpdateSchema;

            var sessionFactory = CreateSessionFactory(bCreateOrUpdateSchema);
            using (var session = sessionFactory.OpenSession())
            {
                if (bCreateSampleData)
                {
                    CreateSampleData(session);
                }

                // get an entity by ID:
                int employeeID = 1;
                var emp = session.Get<Employee>(employeeID);
                Console.WriteLine(String.Format("Employee ID {0} = {1}", employeeID, emp.FirstName));

                int storeID = 1;
                var store = session.Get<Store>(storeID);
                Console.WriteLine(String.Format("Store ID {0} = {1}", storeID, store.Name));

                // add a new employee:
                var newEmp = new Employee { FirstName = "Buzz", LastName = "Lightyear" };
                store.AddEmployee(newEmp);
                session.Flush();

                // query an entity using criteria query:
                var crit = session.CreateCriteria<Employee>()
                    .Add(Expression.Eq("FirstName", "Buzz"));

                IList<Employee> emps = crit.List<Employee>();

                foreach (var empl in emps)
                {
                    Console.WriteLine("Employee :" + empl.FirstName);
                }

                // modify an employee:
                emp = emps.First();
                emp.LastName = "Smith";
                session.Flush();

                // list all employees in a store
                foreach (var empl in store.Staff)
                {
                    Console.WriteLine(String.Format("Store {0} employee: {1} {2}",
                                            store.Name,
                                            empl.FirstName,
                                            empl.LastName));
                }

                // delete all Buzzes

                emps = session.CreateCriteria<Employee>()
                    .Add(Expression.Eq("FirstName", "Buzz"))
                    .List<Employee>();
                foreach (var empl in emps)
                {
                    Console.WriteLine(String.Format("Deleting employee {0} {1}", empl.FirstName, empl.LastName));

                    // you must remove the entity from associated collections, if you only do session.delete, you get an exception when doing session.flush()
                    store.Staff.Remove(empl);
                    session.Delete(empl);
                }
                session.Flush();

                // re-list employees for one store:
                foreach (var empl in store.Staff)
                {
                    Console.WriteLine(String.Format("Store {0} employee: {1} {2}",
                                            store.Name,
                                            empl.FirstName,
                                            empl.LastName));
                }

                // two in memory instances of the same entity,  NHibernate is smart enough to get emp2 from the in memory version(not going back to the database)
                // or at least the changes to emp1 are reflected in emp2:
                var emp1 = session.Get<Employee>(1);
                emp1.FirstName = "Sally";
                var emp2 = session.Get<Employee>(1);
                Console.WriteLine(String.Format("First employee instance: {0} {1}, second employee instance {2} {3}", emp1.FirstName, emp2.LastName, emp2.FirstName, emp2.LastName));

                // its also smart enough to update other instances of the employee when we do this:
                emp1.FirstName = "Daisy";
                emp2.FirstName = "Sarah";
                Console.WriteLine();
                // both emp1 and emp2 now have a firstname of "Sarah"
                Console.WriteLine(String.Format("First employee instance: {0} {1}, second employee instance {2} {3}", emp1.FirstName, emp2.LastName, emp2.FirstName, emp2.LastName));
                session.Flush();

                // are queries smart enough to use already loaded objects?
                var empQuery = session.CreateCriteria<Employee>()
                                .Add(Expression.Eq("FirstName", "Sarah"))
                                .Add(Expression.Eq("LastName", "Harrison"));

                emp1 = empQuery.List<Employee>().First();

                emp1.FirstName = "Danielle";

                var empQuery2 = session.CreateCriteria<Employee>()
                                .Add(Expression.Eq("FirstName", "Danielle"));
                // this query returns nothing, because it goes back to the database:
                Console.WriteLine("Query results for firstname=Danielle:");
                foreach (var empl in empQuery2.List<Employee>())
                {
                    Console.WriteLine(String.Format("{0} {1}", empl.FirstName, empl.LastName));
                }

                // we could probably re-use empQuery here, (but has that already been evaluated? if we call .List() again does it re-query?)
                var empQuery3 = session.CreateCriteria<Employee>()
                                .Add(Expression.Eq("FirstName", "Sarah"));
                // this query returns a  value because the firstname is still sarah in the database
                // but the value displayed is from the in-memory version, so the results of the query shows "danielle", not "sarah":

                Console.WriteLine("Query results for firstname=Sarah:");
                foreach (var empl in empQuery3.List<Employee>())
                {
                    Console.WriteLine(String.Format("{0} {1}", empl.FirstName, empl.LastName));
                }

                Console.WriteLine("Press any key to exit");
                Console.ReadKey();
            }
        }