Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在Nhibernate中保存和查询元素_C#_Sqlite_Nhibernate_Fluent Nhibernate_Queryover - Fatal编程技术网

C# 在Nhibernate中保存和查询元素

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 :

我有两个非常简单的类,一个是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 : 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语义,需要将
    item
    s添加到`store。实际上,这意味着增加这两行:

    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
中的表名,因此默认规则适用(除非您为类/表名实现了
约定

最后注释:

  • NHibernate现在通过
    session.Query()
    支持
    IQueryable
    ; 因此,您可以使用它来代替
    session.QueryOver()
    。如果你是 已经习惯于编写Linq查询,或者如果您来自EF 在这个世界上,您可以像您一样继续编写Linq查询 通常是这样。有时Linq无法满足您的需要,您必须使用
    QueryOver
    。当
    QueryOver
    无法满足您的需要时,您就必须使用
    CreateCriteria
    ,这样的情况甚至更少。有时,这些都对您不利,您必须编写原始sql。但大多数情况下,包括在本例中,Linq会带你去你要去的地方
  • NHibernate现在还支持
    async/await
    模式。您只需使用NHibernate.Linq添加
    并且它们将变得可用。对于此代码,您可以使用
    SaveOrUpdateAsync()
    SingleOrDefaultAsync()
    api代替非异步版本
  • 因为你使用的是流畅的NHiBiNATE,所以考虑使用自动机。相信我,编写映射文件一点也不有趣,而且您只想在绝对必要的情况下编写一个映射文件
    需要注意的一点是,另一种方法是只将项目添加到存储
    项目
    集合,然后只需保存存储实体(由于存储项目映射中的
    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();