使用NHibernate 3.2实现Repository(ORuM)(十二)Repository、LINQ

一世执手 提交于 2020-04-03 14:34:08

接NHibernate 3.2实现Repository(ORuM)前文

使用NHibernate-->NHibernate.Linq-->Linq,结合NHibernate和LINQ的优势,使Repository的对象持久化和对象查询两方面兼优,实现了鱼和熊掌兼得。 

使用LINQ重构Repository

修改Repository接口,使用LINQ减少方法,查询方法只有Query<TEntity>()。

using System;using System.Collections.Generic;using System.Linq;namespace MVCQuick.Framework.Repository{    public interface IRepository : IDisposable    {              void Save<TEntity>(TEntity entity) where TEntity : EntityBase;               void Update<TEntity>(TEntity entity) where TEntity : EntityBase;           void SaveOrUpdate<TEntity>(TEntity entity) where TEntity : EntityBase;                void Delete<TEntity>(TEntity entity) where TEntity : EntityBase;             TEntity Get<TEntity>(int id) where TEntity : EntityBase;               IQueryable<TEntity> Query<TEntity>();             ITransaction BeginTransaction();    }}

NHibernate 实现

using System;using System.Collections.Generic;using System.Linq;using NH = NHibernate;using NHibernate.Linq;namespace MVCQuick.Framework.Repository.NHibernate{       public class NHibernateRepository : IRepository    {        private NH.ISession session;        private bool useNHibernateManager = true;             public NHibernateRepository()        {        }        public NHibernateRepository(NH.ISession session)        {            this.session = session;            this.useNHibernateManager = false;        }        public NH.ISession Session        {            get            {                if (!useNHibernateManager)                {                    return session;                }                else                {                    return NHibernateManager.GetCurrentSession();                }            }        }        public void Save<TEntity>(TEntity entity) where TEntity : EntityBase        {            NH.ISession session = Session;            session.Save(entity);            session.Flush();        }              public void Update<TEntity>(TEntity entity) where TEntity : EntityBase        {            NH.ISession session = Session;            session.Update(entity);            session.Flush();        }            public void SaveOrUpdate<TEntity>(TEntity entity) where TEntity : EntityBase        {            NH.ISession session = Session;            session.SaveOrUpdate(entity);            session.Flush();        }          public void Delete<TEntity>(TEntity entity) where TEntity : EntityBase        {            NH.ISession session = Session;            session.Delete(entity);            session.Flush();        }                  public TEntity Get<TEntity>(int id) where TEntity : EntityBase        {            NH.ISession session = Session;            return session.Get<TEntity>(id);        }                  public IQueryable<TEntity> Query<TEntity>()        {            NH.ISession session = Session;            return session.Query<TEntity>();        }          public ITransaction BeginTransaction()        {            NH.ISession session = Session;            return new NHibernateTransaction(session);        }        public void Dispose()        {            if (this.session != null)            {                this.session.Flush();                CloseSession();            }        }           private void CloseSession()        {            session.Close();            session.Dispose();            session = null;        }    }}

 

AutoMapping部分代码见以前文章。


Repository成效

寥寥几行代码就实现了一个复杂的数据存储层,似乎不可思议,那就看看使用效果如何。

1、定义实体类

 

Entities.cs
using System;using System.Collections.Generic;namespace MVCQuick.Framework.Tests{    public class Album : EntityBase    {        public string Title { get; set; }        public decimal Price { get; set; }                public string AlbumArtUrl { get; set; }        public Genre Genre { get; set; }        public Artist Artist { get; set; }        public void Add()        {        }    }    public class Genre : EntityBase    {        public string Name { get; set; }        public string Description { get; set; }        public IEnumerable<Album> Albums { get; set; }    }    public class Artist : EntityBase    {        public string Name { get; set; }        public Address Address { get; set; }        public IEnumerable<Album> Albums { get; set; }        public IDictionary<String, String> Settings { get; set; }    }    public class User : EntityBase    {        public string Username { get; set; }        public string Email { get; set; }        public string Password { get; set; }        public IEnumerable<Role> Roles { get; set; }        public User() { Roles = new List<Role>(); }    }    public class Role : EntityBase    {        public string Name { get; set; }        public string Description { get; set; }        public IEnumerable<User> Users { get; set; }        public Role() { Users = new List<User>(); }    }    public class Address : IValueObject    {        public string City { get; set; }        public string Country { get; set; }        public string State { get; set; }        public string Street { get; set; }        public string Zip { get; set; }    }}

2、CRUD

        IRepository repository = new NHibernateRepository();        User user = new User { Username = "admin", Email = "admin@163.com", Password = "admin123" };        repository.Save(user);        user = repository.Get<User>(1);        user.Password = "123456";        repository.Update(user);        user = repository.Get<User>(1);        repository.Delete(user);



3、Transaction

         IRepository repository = new NHibernateRepository();        var Users = new List<User>        {            new User { Username = "刘备" , Email = "lb@123.com", Password = "123456" },            new User { Username = "曹操" , Email = "cc@123.com", Password = "123456"  },            new User { Username = "孙权" , Email = "sq@123.com", Password = "123456"  },            new User { Username = "曹植" , Email = "cz@123.com"},            new User { Username = "曹丕" , Email = "cp@123.com"},            new User { Username = "张飞" },            new User { Username = "关羽" },            new User { Username = "赵云" }        };        ITransaction unitOfWork = repository.BeginTransaction();
        foreach (var u in Users)        {            repository.Save(u);        }
        unitOfWork.Commit();  

4、Query

        IList<User> users;        User user = null;        users =            repository.Query<User>()            .ToList<User>();        Assert.AreEqual(users.Count, 8);        //Where        users = repository.Query<User>()            .Where(x => x.Username == "刘备").ToList<User>();        Assert.AreEqual(users.Count, 1);        Assert.AreEqual(users[0].Username, "刘备");        //OrderBy        users = repository.Query<User>()          .OrderByDescending(x => x.Id).ToList();        Assert.AreEqual(users[0].Username, "赵云");        //Skip, Take        users = repository.Query<User>()            .Skip(1 * 3).Take(3).ToList();        Assert.AreEqual(users.Count, 3);        Assert.AreEqual(users[0].Username, "曹植");        //SingleOrDefault        user = repository.Query<User>()            .SingleOrDefault(x => x.Username == "刘备");        Assert.IsNotNull(user);        Assert.AreEqual(user.Username, "刘备");        user = repository.Query<User>()            .SingleOrDefault(x => x.Username == "诸葛亮");        Assert.IsNull(user);        user = repository.Query<User>()           .Where(x => x.Username == "刘备")           .Where(x => x.Email == "lb@123.com")          .SingleOrDefault();        Assert.IsNotNull(user);        Assert.AreEqual(user.Username, "刘备");        //Count        int count = repository.Query<User>()           .Where(x => x.Email != null || x.Email.Length <= 0)           .Count();        Assert.AreEqual(count, 5);    }

Repository执行过程分析

1、实体类自动生成的HBM文件

<?xml version="1.0" encoding="utf-8"?><hibernate-mapping xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" namespace="MVCQuick.Framework.Tests" assembly="MVCQuick.Framework.Tests" xmlns="urn:nhibernate-mapping-2.2">  <class name="Album" lazy="false" table="MVCQuickTest_Albums">    <id name="Id" column="AlbumId" type="Int32">      <generator class="identity"/>    </id>    <version name="Version"/>    <property name="Title"/>    <property name="Price"/>    <property name="AlbumArtUrl"/>    <many-to-one name="Genre" column="GenreId"/>    <many-to-one name="Artist" column="ArtistId"/>  </class>  <class name="Genre" lazy="false" table="MVCQuickTest_Genres">    <id name="Id" column="GenreId" type="Int32">      <generator class="identity"/>    </id>    <version name="Version"/>    <property name="Name"/>    <property name="Description"/>    <bag name="Albums" inverse="true" cascade="all">      <key column="GenreId"/>      <one-to-many class="Album"/>    </bag>  </class>  <class name="Artist" lazy="false" table="MVCQuickTest_Artists">    <id name="Id" column="ArtistId" type="Int32">      <generator class="identity"/>    </id>    <version name="Version"/>    <property name="Name"/>    <component class="Address" name="Address">      <property name="City"/>      <property name="Country"/>      <property name="State"/>      <property name="Street"/>      <property name="Zip"/>    </component>    <bag name="Albums" inverse="true" cascade="all">      <key column="ArtistId"/>      <one-to-many class="Album"/>    </bag>    <map name="Settings" table="MVCQuickTest_ArtistSettings" lazy="false">      <key column="ArtistId"/>      <map-key type="String"/>      <element type="String"/>    </map>  </class>  <class name="User" lazy="false" table="MVCQuickTest_Users">    <id name="Id" column="UserId" type="Int32">      <generator class="identity"/>    </id>    <version name="Version"/>    <property name="Username"/>    <property name="Email"/>    <property name="Password"/>    <bag name="Roles" table="MVCQuickTest_RolesUsers" lazy="false">      <key column="UserId"/>      <many-to-many class="Role" column="RoleId"/>    </bag>  </class>  <class name="Role" lazy="false" table="MVCQuickTest_Roles">    <id name="Id" column="RoleId" type="Int32">      <generator class="identity"/>    </id>    <version name="Version"/>    <property name="Name"/>    <property name="Description"/>    <bag name="Users" table="MVCQuickTest_RolesUsers" lazy="false">      <key column="RoleId"/>      <many-to-many class="User" column="UserId"/>    </bag>  </class></hibernate-mapping>       

 

2、自动生成的Sql建表语句

    PRAGMA foreign_keys = OFF    drop table if exists MVCQuickTest_Albums    drop table if exists MVCQuickTest_Genres    drop table if exists MVCQuickTest_Artists    drop table if exists MVCQuickTest_ArtistSettings    drop table if exists MVCQuickTest_Users    drop table if exists MVCQuickTest_RolesUsers    drop table if exists MVCQuickTest_Roles    PRAGMA foreign_keys = ON    create table MVCQuickTest_Albums (        AlbumId  integer primary key autoincrement,       Version INT not null,       Title TEXT,       Price NUMERIC,       AlbumArtUrl TEXT,       GenreId INT,       ArtistId INT,       constraint FKC10717EEF1D1C255 foreign key (GenreId) references MVCQuickTest_Genres,       constraint FKC10717EEAECFE1CE foreign key (ArtistId) references MVCQuickTest_Artists    )    create table MVCQuickTest_Genres (        GenreId  integer primary key autoincrement,       Version INT not null,       Name TEXT,       Description TEXT    )    create table MVCQuickTest_Artists (        ArtistId  integer primary key autoincrement,       Version INT not null,       Name TEXT,       City TEXT,       Country TEXT,       State TEXT,       Street TEXT,       Zip TEXT    )    create table MVCQuickTest_ArtistSettings (        ArtistId INT not null,       id TEXT,       idx TEXT not null,       primary key (ArtistId, idx),       constraint FK62D35A09AECFE1CE foreign key (ArtistId) references MVCQuickTest_Artists    )    create table MVCQuickTest_Users (        UserId  integer primary key autoincrement,       Version INT not null,       Username TEXT,       Email TEXT,       Password TEXT    )    create table MVCQuickTest_RolesUsers (        UserId INT not null,       RoleId INT not null,       constraint FK92B56EE2860D4243 foreign key (RoleId) references MVCQuickTest_Roles,       constraint FK92B56EE27DFC8936 foreign key (UserId) references MVCQuickTest_Users    )    create table MVCQuickTest_Roles (        RoleId  integer primary key autoincrement,       Version INT not null,       Name TEXT,       Description TEXT    )

 

3、生成的Sql查询语句

select user0_.UserId as UserId16_, user0_.Version as Version16_, user0_.Username as Username16_, user0_.Email as Email16_, user0_.Password as Password16_ from MVCQuickTest_Users user0_select user0_.UserId as UserId16_, user0_.Version as Version16_, user0_.Username as Username16_, user0_.Email as Email16_, user0_.Password as Password16_ from MVCQuickTest_Users user0_ where user0_.Username=@p0;@p0 = '刘备' [Type: String (0)]select user0_.UserId as UserId16_, user0_.Version as Version16_, user0_.Username as Username16_, user0_.Email as Email16_, user0_.Password as Password16_ from MVCQuickTest_Users user0_ order by user0_.UserId descselect user0_.UserId as UserId16_, user0_.Version as Version16_, user0_.Username as Username16_, user0_.Email as Email16_, user0_.Password as Password16_ from MVCQuickTest_Users user0_ limit @p0 offset @p1;@p0 = 3 [Type: Int32 (0)], @p1 = 3 [Type: Int32 (0)]select user0_.UserId as UserId16_, user0_.Version as Version16_, user0_.Username as Username16_, user0_.Email as Email16_, user0_.Password as Password16_ from MVCQuickTest_Users user0_ where user0_.Username=@p0;@p0 = '刘备' [Type: String (0)]select user0_.UserId as UserId16_, user0_.Version as Version16_, user0_.Username as Username16_, user0_.Email as Email16_, user0_.Password as Password16_ from MVCQuickTest_Users user0_ where user0_.Username=@p0;@p0 = '诸葛亮' [Type: String (0)]select user0_.UserId as UserId16_, user0_.Version as Version16_, user0_.Username as Username16_, user0_.Email as Email16_, user0_.Password as Password16_ from MVCQuickTest_Users user0_ where user0_.Username=@p0 and user0_.Email=@p1;@p0 = '刘备' [Type: String (0)], @p1 = 'lb@123.com' [Type: String (0)]select cast(count(*) as INT) as col_0_0_ from MVCQuickTest_Users user0_ where user0_.Email is not null or length(user0_.Email)<=@p0;@p0 = 0 [Type: Int32 (0)]

 

一切尽在掌握!

 

Repository(ORuM)的实现过程感兴趣,可以看看前面的博文,在此不再详述。 

源代码下载:http://mvcquick.codeplex.com/   

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!