C# 在Nhibernate中保存和查询元素
我有两个非常简单的类,一个是Store类,其编码如下 商店C# 在Nhibernate中保存和查询元素,c#,sqlite,nhibernate,fluent-nhibernate,queryover,C#,Sqlite,Nhibernate,Fluent Nhibernate,Queryover,我有两个非常简单的类,一个是Store类,其编码如下 商店 class Store { public virtual int StoreID { get; set; } public virtual string Name { get; set; } public virtual ICollection<Item> ItemID { get; set; } } Fluent Nhiberate的映射如下所示 StoreMap class StoreMap :
class Store
{
public virtual int StoreID { get; set; }
public virtual string Name { get; set; }
public virtual ICollection<Item> ItemID { get; set; }
}
Fluent Nhiberate的映射如下所示
StoreMap
class StoreMap : ClassMap<Store>
{
public StoreMap()
{
Id(x => x.StoreID).Column("idStore").GeneratedBy.Assigned();
Map(x => x.Name).Column("Name").Not.Nullable();
HasMany(x => x.ItemID).KeyColumn("idItem").Inverse().Table("Item").AsSet().Cascade.SaveUpdate();
}
}
class ItemMap : ClassMap<Item>
{
public ItemMap()
{
Id(x => x.ItemID).Column("idItem").GeneratedBy.Assigned();
Map(x => x.Name).Column("Name").Not.Nullable();
Map(x => x.Price).Column("Price").Default("0");
Map(x => x.Quantity).Column("Quantity").Default("0");
References(x => x.StoreID).Column("idStore");
}
}
当我查询以从存储中获取所有数据时,只有第一个项目显示在项目列表中
Store s = session.QueryOver<Store>().Where(x => x.StoreID == 1).SingleOrDefault<Store>();
stores=session.QueryOver().Where(x=>x.StoreID==1.SingleOrDefault();
所以我的问题是,我应该如何查询和保存以获得尽可能少的代码行,并在商店列表中同时获得这两个项目?- 为了保存,由于您映射实体的方式,
特别是因为级联选项集
(
),您可以愉快地删除.Cascade.SaveUpdate()
session.SaveOrUpdate(i2)代码>和
session.SaveOrUpdate(i1)代码>。只是 保存
将自动保存这些内容s
- 要维护OO语义,需要将
s添加到`store。实际上,这意味着增加这两行:item
s.ItemID.Add(i1); s.ItemID.Add(i2);
- 您可以使用
语句简化会话的创建和销毁(关闭)using
Store s = // as defined earlier;
Item i1 = // as defined earlier;
Item i2 = // as defined earlier;
s.ItemID.Add(i1);
s.ItemID.Add(i2);
using (var session = NhConfig.GetSession())
{
var trans = session.BeginTransaction();
try
{
session.SaveOrUpdate(s);
trans.Commit();
}
catch (Exception)
{
trans.Rollback();
throw;
}
}
// Later when you need to query
using (var session = NhConfig.GetSession())
{
Store store = session.QueryOver<Store>().Where(x => x.StoreID == 1).SingleOrDefault();
foreach (var item in store.ItemID) // store.ItemID.Count == 2.
{
Console.WriteLine($"Item - Id: {item.ItemID}. Name: {item.Name}. Store ID: {item.StoreID.StoreID}.");
}
/* The above loop will print:
Item - Id: 1. Name: Item 1. Store ID: 1.
Item - Id: 2. Name: Item 2. Store ID: 1.
*/
}
到
请注意所做的更改:.KeyColumn现在命名为“idStore”,而不是“idItem”。.HasMany(…)
侧的键列名必须与.References(…)
侧的列名相对应
.Table(“Item”)
是多余的,因为默认情况下,“Item”将是名为Item
的类的表名。由于您没有弄乱ItemMap
中的表名,因此默认规则适用(除非您为类/表名实现了约定
)
最后注释:
session.Query()
支持IQueryable
;
因此,您可以使用它来代替session.QueryOver()
。如果你是
已经习惯于编写Linq查询,或者如果您来自EF
在这个世界上,您可以像您一样继续编写Linq查询
通常是这样。有时Linq无法满足您的需要,您必须使用QueryOver
。当QueryOver
无法满足您的需要时,您就必须使用CreateCriteria
,这样的情况甚至更少。有时,这些都对您不利,您必须编写原始sql。但大多数情况下,包括在本例中,Linq会带你去你要去的地方async/await
模式。您只需使用NHibernate.Linq添加代码>并且它们将变得可用。对于此代码,您可以使用SaveOrUpdateAsync()
和SingleOrDefaultAsync()
api代替非异步版本
需要注意的一点是,另一种方法是只将项目添加到存储
项目集合,然后只需保存存储实体(由于存储项目映射中的Cascade.SaveUpdate()
),您已经正确地使用了Cascade
(我确实使用了所有孤立项,但是..)。这意味着,不需要对项目调用会话保存。他们将坚持下去。。如果我们也将它们添加到商店的集合项目
好的,我已经改变了将项目
元素添加到商店
列表中的方式。但是,当我使用Store s=session.QueryOver().Where(x=>x.StoreID==1.SingleOrDefault())查询以获取Store元素时,仍然无法在列表中同时包含这两个项代码>
s.ItemID.Add(i1);
s.ItemID.Add(i2);
Store s = // as defined earlier;
Item i1 = // as defined earlier;
Item i2 = // as defined earlier;
s.ItemID.Add(i1);
s.ItemID.Add(i2);
using (var session = NhConfig.GetSession())
{
var trans = session.BeginTransaction();
try
{
session.SaveOrUpdate(s);
trans.Commit();
}
catch (Exception)
{
trans.Rollback();
throw;
}
}
// Later when you need to query
using (var session = NhConfig.GetSession())
{
Store store = session.QueryOver<Store>().Where(x => x.StoreID == 1).SingleOrDefault();
foreach (var item in store.ItemID) // store.ItemID.Count == 2.
{
Console.WriteLine($"Item - Id: {item.ItemID}. Name: {item.Name}. Store ID: {item.StoreID.StoreID}.");
}
/* The above loop will print:
Item - Id: 1. Name: Item 1. Store ID: 1.
Item - Id: 2. Name: Item 2. Store ID: 1.
*/
}
HasMany(x => x.ItemID).KeyColumn("idItem").Inverse().Table("Item").AsSet().Cascade.SaveUpdate();
HasMany(x => x.ItemID).KeyColumn("idStore").Inverse().AsSet().Cascade.SaveUpdate();