NHibernate中元素的保存与查询:基于Store和Item类的技术咨询
Hey there! Let's break down how to implement save and query operations for your Store and Item entities in NHibernate. First, a quick note: we'll need to tweak your entity classes and set up mappings (since NHibernate relies on these to map C# classes to database tables properly).
Step 1: Adjust Entity Classes
Your current definitions are missing key pieces for proper association. Let's update them for clarity and relationship support:
public class Store { public virtual int StoreID { get; set; } public virtual string Name { get; set; } // Renamed from ItemID to Items for readability (this is the collection of related items) public virtual ICollection<Item> Items { get; set; } = new List<Item>(); } public class Item { public virtual int ItemID { get; set; } public virtual string Name { get; set; } public virtual double Price { get; set; } public virtual int Quantity { get; set; } // Added navigation property back to Store (required for one-to-many relationship) public virtual Store Store { get; set; } }
Step 2: Set Up NHibernate Mappings
We'll use Fluent NHibernate here (it's more concise than XML mappings). Create mapping classes for each entity:
// StoreMap.cs public class StoreMap : ClassMap<Store> { public StoreMap() { Id(x => x.StoreID); // Maps StoreID to the primary key column Map(x => x.Name); // Maps Name to a database column // Configure one-to-many relationship with Item HasMany(x => x.Items) .Inverse() // Indicates Item owns the relationship (via its Store property) .Cascade.All(); // Automatically save/update/delete related Items when Store is modified } } // ItemMap.cs public class ItemMap : ClassMap<Item> { public ItemMap() { Id(x => x.ItemID); Map(x => x.Name); Map(x => x.Price); Map(x => x.Quantity); // Configure many-to-one relationship back to Store References(x => x.Store) .Column("StoreID"); // Maps to the foreign key column in the Items table } }
Step 3: Create SessionFactory
Initialize the NHibernate SessionFactory (do this once at app startup):
var sessionFactory = Fluently.Configure() .Database(MsSqlConfiguration.MsSql2012 // Adjust to your database provider (e.g., SQLite, PostgreSQL) .ConnectionString("Your_Database_Connection_String_Here")) .Mappings(m => m.FluentMappings.AddFromAssemblyOf<StoreMap>()) // Load mappings from your project's assembly .BuildSessionFactory();
Step 4: Save Operations
Save a Single Item
using (var session = sessionFactory.OpenSession()) using (var transaction = session.BeginTransaction()) { var newItem = new Item { Name = "Wireless Headphones", Price = 199.99, Quantity = 25 }; session.Save(newItem); transaction.Commit(); // Always commit transactions for write operations to ensure data consistency }
Save a Store with Associated Items
Thanks to the Cascade.All setting, saving the Store will automatically save its related Items:
using (var session = sessionFactory.OpenSession()) using (var transaction = session.BeginTransaction()) { var newStore = new Store { Name = "Audio Hub", Items = new List<Item> { new Item { Name = "Bluetooth Speaker", Price = 89.99, Quantity = 15 }, new Item { Name = "Noise Canceling Headphones", Price = 299.99, Quantity = 10 } } }; session.Save(newStore); transaction.Commit(); }
Step 5: Query Operations
We'll cover common scenarios using LINQ to NHibernate (intuitive) and HQL (SQL-like syntax).
Query a Store with Its Items (Avoid N+1 Queries)
Use Fetch to load related Items in a single query:
using (var session = sessionFactory.OpenSession()) { var store = session.Query<Store>() .Fetch(s => s.Items) // Eagerly load associated Items to prevent lazy loading issues .FirstOrDefault(s => s.StoreID == 1); if (store != null) { Console.WriteLine($"Store: {store.Name}"); foreach (var item in store.Items) { Console.WriteLine($"Item: {item.Name} | Price: ${item.Price} | Qty: {item.Quantity}"); } } }
Query Items by Price
using (var session = sessionFactory.OpenSession()) { var premiumItems = session.Query<Item>() .Where(i => i.Price > 100) .OrderByDescending(i => i.Price) .ToList(); foreach (var item in premiumItems) { Console.WriteLine($"Item: {item.Name} | Price: ${item.Price}"); } }
Query with HQL
If you prefer a SQL-style approach:
using (var session = sessionFactory.OpenSession()) { var hql = "FROM Item i WHERE i.Store.Name = :storeName"; var itemsFromStore = session.CreateQuery(hql) .SetParameter("storeName", "Audio Hub") .List<Item>(); // Process results here }
Key Notes
- Always use transactions for write operations (save/update/delete) to keep your data consistent.
- Use
FetchorFetchManyto avoid N+1 query problems when accessing related entities. - Adjust the database provider configuration to match your actual database system (e.g.,
SqliteConfiguration,PostgreSQLConfiguration).
内容的提问来源于stack exchange,提问作者a.ras2002

