NHibernate初学者指南

By admin in 天文学 on 2019年3月13日

在前方的《NHibernate初学者指南(8):增加和删除查改》一文中回顾的关联了询问三个实体的Get<T>和Load<T>方法以及询问实体列表的Query<T>方法,那篇文章大家越来越讲解查询的关于地方。

理论知识

界定重临的记录数

var orders = session.Query<Order>();

上边的查询重临Order表中兼有的订单,假使想限制重返记录的个数,能够使用Take方法,如上边包车型大巴代码:

var orders = session.Query<Order>().Take(200);

筛选记录集

行使筛选的机要字是Where。LINQ定义了多个Where方法,它将三个谓词作者为参数。谓词是富含二个参数的函数它回到3个布尔值,如下边包车型客车代码所示:

Func<T, bool> predicate

一旦要询问全部下架的制品,能够运用上边包车型地铁代码:

var discontinuedProducts = session
    .Query<Product>()
    .Where(p => p.Discontinued);

下面的查询中,大家采纳3个Lamb达表达式p=>p.Discontinued定义谓词。那些表达式的意味是:给定贰个产品p,获取它的Discontinued属性的始末并回到。假使回到的值是true,那么相应的产品就包涵在筛选的结果集中。

照耀记录集

辉映记录集能够应用Select方法,它将叁个映射函数作为参数。映射函数定义为如下代码:

Func<TSource, TResult> mapper

若果我们想加载下架的成品列表,不过唯有产品的Id和Name。咱们得以先定义叁个类NameID,如下所示:

public class NameID
{
    public int Id { get; set; }
    public string Name { get; set; }
}

查询如下所示:

var discontinuedProducts = session
                           .Query<Product>()
                           .Where(p => p.Discontinued)
                           .Select(p => new NameID { Id = p.Id, Name = p.Name });

上边的代码大家定义了映射函数作为Lamb达表明式,如上面包车型大巴代码:

p => new NameID { Id = p.Id, Name = p.Name }

它的趣味是经受一个Product对象p并再次回到三个NameID类型的对象,它的性质为:Id和Name,对应于产品p的Id和Name。

排序结果集

一经大家想取得Person对象的列表,按姓氏排序,如下边的代码所示:

var people = session.Query<Person>()
            .OrderBy(p => p.LastName);

假如我们还想规行矩步first name排序,那么查询如下所示:

var people = session.Query<Person>()
            .OrderBy(p => p.LastName)
            .ThenBy(p => p.FirstName);

专注我们能够遵循多少个列排序,只要求不难的在后边调用ThenBy方法即可。还有与OrderBy和ThenBy绝对应的是遵照降序排列的法门:OrderByDescending和ThenByDescending。上面的查询依据相反的顺序排列,如下边包车型大巴代码所示:

var people = session.Query<Person>()
            .OrderByDescending(p => p.LastName)
            .ThenByDescending(p => p.FirstName);

分组记录

一经我们想总结有稍许个人的姓氏以同等的字母起首,那么我们得以依赖分组函数,代码如下所示:

var personsPerLetter = session.Query<Person>()
                       .GroupBy(p => p.LastName.Substring(0, 1))
                       .Select(g => new { Letter = g.Key, Count = g.Count() });

上边包车型地铁代码再次回到匿名类型的列表,它富含想要的结果。

GroupBy方法再次回到IEnumerable<IGrouping<T,V>>,T表示分组依据的值的品种,V表示被分组的花色。在上头的代码中,T是string类型的,V是Person类型的。

强制LINQ查询立刻施行

LINQ查询总是延迟执行的,只有当我们初步遍历结果集时查询才真的的实践。可是有时,我们想强制执行查询并赶回结果集。有两样的情势得以如此做。

首先,大家能够调用扩大方法ToArray或ToList终止查询。那五个点子马上开头枚举结果集并将结果对象放置数组或列表中。

var products = session.Query<Product>()
               .Where(p => p.ReorderLevel > p.UnitsOnStock)
               .ToArray();

地方的询问加载全部供给再行订货的全数产品列表,并将它们放入到一个数组中。

第①,使用ToDictionary方法。那一个点子在从数据库中摸索出实体列表并为每1个实例使用唯一键存款和储蓄在聚集中十一分方便。我们看三个事例,如上边包车型大巴代码所示:

var personsPerLetter = session.Query<Person>()
                       .GroupBy(p => p.LastName.Substring(0, 1))
                       .Select(g => new { Letter = g.Key, Count = g.Count() })
                       .ToDictionary(x => x.Letter, x => x.Count);

地点的询问创立了七个总人口的字典,它的姓氏以给定的假名初叶。key是姓氏的伊始字母,value是人口。

从查询数据库改为查询内部存款和储蓄器对象

又是,大家想从数据库查询部分数据,然后一发采取底层数据库不帮忙的职能操作那个数量。那种情景,大家必要一种办法布告LINQ
to
NHibernate提供程序从以后起全部的操作都在内部存款和储蓄器中成功而不是数据库中。为此,大家得以选用AsEnumerable方法。

让大家看二个例证。假诺有四个Email实体,它涵盖部分记录。未来,大家想生成一个邮件的筛选列表,筛选标准是一个正则表明式。不过,超越一三分之一据库不扶助正则表明式。由此,筛选必须在内部存款和储蓄器中完结,如上边包车型大巴代码所示:

var statusList = session.Query<Email>()
                .Select(e => e.EmailAddress)
                .AsEnumerable()
                .Where(e => SomeFilterFunctionUsingRegExp(e));

上边的例子,投影产生在数据库,而筛选在内部存款和储蓄器中做到。

选择LINQ to NHibernate创立报表

为了熟习LINQ to
NHibernate的接纳,我们创造多少个例外的表格打字与印刷到显示屏上。在上面的事例中,我们的模子是天文学的一部分,更适用的身为星体分类。大家利用XML配置文件和XML映射文件映射大家的模子。

  1. 在SSMS中开创1个空的数据库:LinqToNHibernate萨姆ple。

  2. 在Visual Studio中创设七个控制台应用程序:LinqToNHibernateSample。

  3. 设置项目标Target Framework为.NET Framework 4。

  4. 加上对NHibernate和NHibernate.ByteCode.Castle程序集的引用。

5.
在消除方案中添加一个缓解方案文件夹:Schema,并丰盛nhibernate-configuration.xsd
和nhibernatemapping.
xsd七个公文。

  1. 在品种中添加二个类公事Star.cs,添加如下代码定义Star实体:

    public class Star
    {

     public virtual Guid Id { get; set; }
     public virtual string Name { get; set; }
     public virtual IList<Planet> Planets { get; set; }
     public virtual StarTypes Class { get; set; }
     public virtual SurfaceColor Color { get; set; }
     public virtual double Mass { get; set; }
    

    }

  2. 在项目中添加一个类公事Planet.cs,添加如下代码定义Planet实体:

    public class Planet
    {

     public virtual Guid Id { get; set; }
     public virtual string Name { get; set; }
     public virtual bool IsHabitable { get; set; }
     public virtual Star Sun { get; set; }
    

    }

8.
在项目中添加一个类公事SurfaceColor.cs,在文件中定义枚举SurfaceColor,代码如下所示:

public enum SurfaceColor
{
    Blue, BueToWhite, WhiteToYellow, OrangeToRed, Red
}

9.
在项目中添加贰个类公事StarTypes.cs,在文件中定义枚举StarTypes,代码如下所示:

public enum StarTypes
{
    O, B, A, F, G, K, M
}
  1. 在项目中添加3个XML文件Star.hbm.xml,设置它的Build
    Action属性为Embedded Resource,并累加如下代码定义Star实体的映照:

    天文学,

    <id name="Id">
      <generator class="guid.comb"/>
    </id>
    <property name="Name"/>
    <property name="Mass"/>
    <property name="Class" type="StarTypes"/>
    <property name="Color" type="SurfaceColor"/>
    <bag name="Planets" inverse="true" cascade="all-delete-orphan">
      <key column="StarId" />
      <one-to-many class="Planet"/>
    </bag>
    


只顾Star实体的八个枚举类型属性Color和Class是什么样映射的。我们利用type脾气内定NHibernate映射这一个属性为数据库的int类型的列(枚举的基类型是int)。别的注意一个star的planets列表是怎么映射的。特别复习一下inverse和cascade特性以及集聚类型的施用。还要注意的是我们使用Guid生成器。

  1. 在类型中添加另1个XML文件Planet.hbm.xml,设置它的Action
    Build属性为Embedded Resource,并累加如下代码映射Planet实体:


                   assembly="LinqToNHibernateSample" 
                   namespace="LinqToNHibernateSample">
    

    <id name="Id">
      <generator class="guid.comb"/>
    </id>
    <property name="Name"/>
    <property name="IsHabitable"/>
    <many-to-one name="Sun" class="Star" column="StarId"/>
    


留神大家在many-to-one标签中运用column个性匹配Star.hbm.xml映射文件中bag标签定义的key。

12.
在档次中添加XML文件hibernate.cfg.xml。那一个文件包括配置音信,代码如下所示:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
  <session-factory name="Sample">
    <property name="connection.provider">
      NHibernate.Connection.DriverConnectionProvider
    </property>
    <property name="connection.driver_class">
      NHibernate.Driver.SqlClientDriver
    </property>
    <property name="dialect">
      NHibernate.Dialect.MsSql2008Dialect
    </property>
    <property name="connection.connection_string">
      server=.;database=LinqToNHibernateSample;integrated security=true
    </property>
    <property name="proxyfactory.factory_class">
      NHibernate.ByteCode.Castle.ProxyFactoryFactory,NHibernate.ByteCode.Castle
    </property>
  </session-factory>
</hibernate-configuration>
  1. 设置hibernate.cfg.xml文件的Copy to Output Directory属性为always。

  2. 在Program类中的Main方法中,添加代码开始化Nhibernate
    Configuration对象,如下所示:

    var configuration = new Configuration();

15.
嗲用configuration对象的Configure方法。那些方法会当前目录中寻觅名为hibernate.cfg.xml的文书,倘使找到,就从中读取全体的配备值,如上边的代码所示:

configuration.Configure();
  1. 丰盛代码告诉configuration对象解析程序集,如下所示:

    configuration.AddAssembly(typeof(Star).Assembly);

  2. 添加代码创立或再次创立数据库架构,如下边包车型客车代码所示:

    new SchemaExport(configuration).Execute(true, true, false);

  3. 采取configuration对象创设三个session工厂,如上边包车型大巴代码所示:

    var factory = configuration.BuildSessionFactory();

  4. 下一场添加如下代码:

    CreateData(factory);
    QueryData(factory);
    Console.Write(“\r\n\nHit enter to exit:”);
    Console.ReadLine();

  5. 上边大家首先完结CreateData方法,代码如下:

    private static void CreateData(ISessionFactory factory)
    {

    var sun = new Star
    {
        Name = "Sun",
        Mass = 1,
        Class = StarTypes.G,
        Color = SurfaceColor.WhiteToYellow
    };
    var planets = new List<Planet>
                    {
                        new Planet{Name = "Merkur", IsHabitable = false, Sun = sun},
                        new Planet{Name = "Venus", IsHabitable = false, Sun = sun},
                    // please consult the sample code for full list of planets
                    };
    sun.Planets = planets;
    var virginis61 = new Star
    {
        Name = "61 Virginis",
        Mass = 0.95,
        Class = StarTypes.G,
        Color = SurfaceColor.WhiteToYellow
    };
    var planets2 = new List<Planet>
                    {
                        new Planet{Name = "Planet 1", IsHabitable = false,Sun = virginis61},
                        new Planet{Name = "Planet 2", IsHabitable = true,Sun = virginis61},
                        new Planet{Name = "Planet 3", IsHabitable = false,Sun = virginis61}
                    };
    virginis61.Planets = planets2;
    var stars = new List<Star>
                {
                    sun, virginis61,
                    new Star{Name = "10 Lacertra", Mass = 60,Class = StarTypes.O, Color = SurfaceColor.Blue},
                    new Star{Name = "Spica", Mass = 18,Class = StarTypes.B, Color = SurfaceColor.Blue},
                    // please consult the sample code for full list of stars
                };
    using (var session = factory.OpenSession())
    using (var tx = session.BeginTransaction())
    {
        foreach (var star in stars)
        {
            session.Save(star);
        }
        tx.Commit();
    }
    

    }

  6. 随后我们落实QueryData方法,代码如下:

    private static void QueryData(ISessionFactory factory)
    {

    using (var session = factory.OpenSession())
    using (var tx = session.BeginTransaction())
    {
        PrintListOfStars(session);
        PrintListOfBigBlueStars(session);
        PrintSumOfStarMassPerClass(session);
        PrintListOfHabitablePlanets(session);
        tx.Commit();
    }
    

    }

专注那一个艺术是怎么制造session,transaction以及在transaction内调用多少个表格方法。上边让我们分别实现地点的多个点子。

22.
让我们首先完成率先个措施,它依照star的名目排种类表并打字与印刷,代码如下所示:

private static void PrintListOfStars(ISession session)
{
    Console.WriteLine("\r\n\nList of stars ------------------\r\n");
    var stars = session.Query<Star>().OrderBy(s => s.Name);
    foreach (var star in stars)
    {
        Console.WriteLine("{0} ({1}, {2})",
        star.Name, star.Class, star.Color);
    }
}

留意上面的代码中,大家是如何使用Query扩张方法得到IQueryable<Star>,然后使用OrderBy方法排序的。别的,注意当大家开头遍历它时查询才会实行。

23.
上面实现第③个情势。大家使用几个天性筛选和排序,甚至是种种颠倒过来,代码如下所示:

private static void PrintListOfBigBlueStars(ISession session)
{
    Console.WriteLine("\r\n\nList of big blue stars -------\r\n");
    var stars = session.Query<Star>()
                .Where(s => s.Color == SurfaceColor.Blue && s.Mass > 15)
                .OrderByDescending(s=>s.Mass)
                .ThenBy(s => s.Name);
    foreach (var star in stars)
    {
        Console.WriteLine("{0} ({1}, {2}, Mass={3})",
        star.Name, star.Class, star.Color, star.Mass);
    }
}

24.
第四个主意,大家分组star列表,并行使三个聚合函数(Sum)总计存款和储蓄在数据库中的star相对品质的总数。代码如下所示:

private static void PrintSumOfStarMassPerClass(ISession session)
{
    Console.WriteLine("\r\n\nSum of masses per class -------\r\n");
    var starMasses = session.Query<Star>()
                    .GroupBy(s => s.Class)
                    .Select(g => new
                                {
                                    Class = g.Key,
                                    TotalMass = g.Sum(s => s.Mass)
                                 }
                            );
    foreach (var mass in starMasses)
    {
        Console.WriteLine("Class={0}, Total Mass={1}",
        mass.Class, mass.TotalMass);
    }
}

25.
最终,大家兑现的艺术是打字与印刷根据Sun和行星的称呼排序的合乎人类居住的行星列表,代码如下所示:

private static void PrintListOfHabitablePlanets(ISession session)
{
    Console.WriteLine("\r\n\nList of habitable planets------\r\n");
    var planets = session.Query<Planet>()
                   .Where(p => p.IsHabitable)
                   .OrderBy(p => p.Sun.Name)
                   .ThenBy(p => p.Name);
    foreach (var planet in planets)
    {
        Console.WriteLine("Star='{0}', Planet='{1}'",
        planet.Sun.Name, planet.Name);
    }
}
  1. 运作程序,结果如下图所示:

天文学 1

总结

首先大家介绍了接纳LINQ to
NHibernate提供程序查询的有个别理论知识,然后通过2个事例
概念了不一样的询问,包蕴筛选、排序、分组和聚众,并将结果集打字与印刷到显示器上。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图
Copyright @ 2010-2019 亚洲必赢手机官网 版权所有