SqlServer与MongoDB结合使用NHibernate

本文实例为大家分享了SqlServer与MongoDB结合使用NHibernate的代码,供大家参考,具体内容如下

Program.cs代码内容:

class Program
 {
   private const string SqlServerConnectionString =
     @"Data Source=.;Initial Catalog=SqlWithMongo;Persist Security Info=True;User ID=sa;Password=123456"; 

   private const string MongoConnectionString = "mongodb://localhost:27017";
   private const int NumberOfNodes = 1000; 

   private static void Main(string[] args)
   {
     Console.WriteLine("Clearing database...");
     ClearDatabases();
     Initer.Init(SqlServerConnectionString, MongoConnectionString);
     Console.WriteLine("Completed"); 

     Console.WriteLine("Creating nodes...");
     //创建sqlserver的Node节点
     CreateNodes();
     Console.WriteLine("Completed"); 

     Console.WriteLine("Linking nodes...");
     long milliseconds1 = LinkSqlNodes(); //创建sqlserver的LinkNode节点
     Console.WriteLine("SQL : " + milliseconds1);
     long milliseconds2 = LinkMongoNodes(); //同时创建Node,LinkNode节点
     Console.WriteLine("Mongo : " + milliseconds2);
     Console.WriteLine("Completed"); 

     Console.WriteLine("Fetching nodes...");
     long milliseconds3 = FetchSqlNodes(); //取出sqlserver节点数据
     Console.WriteLine("SQL : " + milliseconds3);
     long milliseconds4 = FetchMongoNodes(); //取出Mongodb节点数据
     Console.WriteLine("Mongo : " + milliseconds4);
     Console.WriteLine("Completed"); 

     Console.ReadKey();
   } 

   private static long FetchMongoNodes()
   {
     var stopwatch = new Stopwatch();
     stopwatch.Start(); 

     for (int i = 0; i < NumberOfNodes; i++)
     {
       using (var unitOfWork = new UnitOfWork())
       {
         var repository = new MongoNodeRepository(unitOfWork); 

         MongoNode node = repository.GetById(i + 1);
         IReadOnlyList<NodeLink> links = node.Links;
       }
     }
     stopwatch.Stop();
     return stopwatch.ElapsedMilliseconds;
   } 

   private static long FetchSqlNodes()
   {
     var stopwatch = new Stopwatch();
     stopwatch.Start(); 

     for (int i = 0; i < NumberOfNodes; i++)
     {
       using (var unitOfWork = new UnitOfWork())
       {
         var repository = new NodeRepository(unitOfWork); 

         Node node = repository.GetById(i + 1);
         IReadOnlyList<Node> links = node.Links;
       }
     } 

     stopwatch.Stop();
     return stopwatch.ElapsedMilliseconds;
   } 

   private static long LinkSqlNodes()
   {
     var stopwatch = new Stopwatch();
     stopwatch.Start(); 

     using (var unitOfWork = new UnitOfWork())
     {
       var repository = new NodeRepository(unitOfWork); 

       IList<Node> nodes = repository.GetAll();
       foreach (Node node1 in nodes)
       {
         foreach (Node node2 in nodes)
         {
           node1.AddLink(node2);
         }
       }
       unitOfWork.Commit();
     } 

     stopwatch.Stop();
     return stopwatch.ElapsedMilliseconds;
   } 

   private static long LinkMongoNodes()
   {
     var stopwatch = new Stopwatch();
     stopwatch.Start(); 

     using (var unitOfWork = new UnitOfWork())
     {
       var repository = new MongoNodeRepository(unitOfWork); 

       IList<MongoNode> nodes = repository.GetAll();
       foreach (MongoNode node1 in nodes)
       {
         foreach (MongoNode node2 in nodes)
         {
           node1.AddLink(node2);
         }
       }
       unitOfWork.Commit();
     } 

     stopwatch.Stop();
     return stopwatch.ElapsedMilliseconds;
   } 

   private static void CreateNodes()
   {
     using (var unitOfWork = new UnitOfWork())
     {
       var repository = new NodeRepository(unitOfWork); 

       for (int i = 0; i < NumberOfNodes; i++)
       {
         var node = new Node("Node " + (i + 1)); //实例化 构造函数初始化name
         repository.Save(node);
       } 

       unitOfWork.Commit();
     } 

     using (var unitOfWork = new UnitOfWork())
     {
       var repository = new MongoNodeRepository(unitOfWork); 

       for (int i = 0; i < NumberOfNodes; i++)
       {
         var node = new MongoNode("Node " + (i + 1));
         repository.Save(node);
       } 

       unitOfWork.Commit();
     }
   } 

   //清空数据
   private static void ClearDatabases()
   {
     new MongoClient(MongoConnectionString)
       .GetDatabase("sqlWithMongo")
       .DropCollectionAsync("links")
       .Wait(); 

     string query = "DELETE FROM [dbo].[MongoNode];" +
             "DELETE FROM [dbo].[Node_Node];" +
             "DELETE FROM [dbo].[Node];" +
             "UPDATE [dbo].[Ids] SET [NextHigh] = 0"; 

     using (var connection = new SqlConnection(SqlServerConnectionString))
     {
       var command = new SqlCommand(query, connection)
       {
         CommandType = CommandType.Text
       }; 

       connection.Open();
       command.ExecuteNonQuery();
     }
   }
 }

相关辅助类代码如下:

public static class Initer
 {
   public static void Init(string sqlServerConnectionString, string mongoConnectionString)
   {
     //SqlServer初始化
     SessionFactory.Init(sqlServerConnectionString);
     //Mongodb初始化
     NodeLinkRepository.Init(mongoConnectionString);
   }
 }
public static class SessionFactory //工厂
  {
    private static ISessionFactory _factory; 

    internal static ISession OpenSession()
    {
      return _factory.OpenSession(new Interceptor());
    } 

    internal static void Init(string connectionString)
    {
      _factory = BuildSessionFactory(connectionString);
    } 

    private static ISessionFactory BuildSessionFactory(string connectionString)
    {
      //用编程的方式进行配置,让你能更好的理解,不需要编写复杂的映射文件,它能完全替换NHibernate的映射文件,让你在映射的时候能使用C#的强类型方式。
      FluentConfiguration configuration = Fluently.Configure()
        .Database(MsSqlConfiguration.MsSql2012.ConnectionString(connectionString))
        .Mappings(m => m.FluentMappings.AddFromAssembly(Assembly.GetExecutingAssembly()))
        .ExposeConfiguration(x =>
        {
          x.EventListeners.PostLoadEventListeners = new IPostLoadEventListener[]
          {
            new EventListener()
          };
        }); 

      return configuration.BuildSessionFactory();
    }
  }
internal class NodeLinkRepository //仓库 Repository模式
  {
    private static IMongoCollection<NodeLinks> _collection; 

    public IList<NodeLink> GetLinks(int nodeId)
    {
      NodeLinks links = _collection.Find(x => x.Id == nodeId).SingleOrDefaultAsync().Result; 

      if (links == null)
        return new NodeLink[0]; 

      return links.Links;
    } 

    public Task SaveLinks(int nodeId, IEnumerable<NodeLink> links)
    {
      var nodeLinks = new NodeLinks(nodeId, links);
      var updateOptions = new UpdateOptions
      {
        IsUpsert = true
      }; 

      return _collection.ReplaceOneAsync(x => x.Id == nodeId, nodeLinks, updateOptions);
    } 

    internal static void Init(string connectionString)
    {
      var client = new MongoClient(connectionString);
      IMongoDatabase database = client.GetDatabase("sqlWithMongo");
      var collectionSettings = new MongoCollectionSettings
      {
        WriteConcern = new WriteConcern(1)
      };
      _collection = database.GetCollection<NodeLinks>("links", collectionSettings);
    } 

    private class NodeLinks
    {
      public int Id { get; private set; }
      public List<NodeLink> Links { get; private set; } 

      public NodeLinks(int nodeId, IEnumerable<NodeLink> links)
      {
        Id = nodeId;
        Links = new List<NodeLink>();
        Links.AddRange(links);
      }
    }
  }
public class NodeRepository
  {
    private readonly UnitOfWork _unitOfWork; 

    public NodeRepository(UnitOfWork unitOfWork)
    {
      _unitOfWork = unitOfWork;
    } 

    public Node GetById(int id)
    {
      return _unitOfWork.Get<Node>(id);
    } 

    public IList<Node> GetAll()
    {
      return _unitOfWork.Query<Node>()
        .ToList();
    } 

    public void Save(Node mongoNode)
    {
      _unitOfWork.SaveOrUpdate(mongoNode);
    }
  }
public class MongoNodeRepository
  {
    private readonly UnitOfWork _unitOfWork; 

    public MongoNodeRepository(UnitOfWork unitOfWork)
    {
      _unitOfWork = unitOfWork;
    } 

    public MongoNode GetById(int id)
    {
      return _unitOfWork.Get<MongoNode>(id);
    } 

    public void Save(MongoNode mongoNode)
    {
      _unitOfWork.SaveOrUpdate(mongoNode);
    } 

    public IList<MongoNode> GetAll()
    {
      return _unitOfWork.Query<MongoNode>()
        .ToList();
    }
  }

模型层数据:
Node.cs,NodeMap.cs类代码如下:

public class Node
  {
    public virtual int Id { get; protected set; }
    public virtual string Name { get; protected set; } 

    protected virtual ISet<Node> LinksInternal { get; set; }
    public virtual IReadOnlyList<Node> Links
    {
      get { return LinksInternal.ToList(); }
    } 

    protected Node()
    {
      LinksInternal = new HashSet<Node>();
    } 

    public Node(string name)
      : this()
    {
      Name = name;
    } 

    public virtual void AddLink(Node node)
    {
      LinksInternal.Add(node);
      node.LinksInternal.Add(this);
    }
  }
public class NodeMap : ClassMap<Node> //FluentNHibernate.Mapping.ClasslikeMapBase<T>
  {
    public NodeMap()
    {
      Id(x => x.Id, "NodeId").GeneratedBy.HiLo("[dbo].[Ids]", "NextHigh", "10", "EntityName = 'Node'");
      Map(x => x.Name).Not.Nullable(); 

      HasManyToMany<Node>(Reveal.Member<Node>("LinksInternal"))
        .AsSet()
        .Table("Node_Node")
        .ParentKeyColumn("NodeId1")
        .ChildKeyColumn("NodeId2");
    }
  }

MongoNode.cs和MongoNodeMap.cs的代码如下:

public class MongoNode
 {
   public virtual int Id { get; protected set; }
   public virtual string Name { get; protected set; } 

   protected virtual HashSet<NodeLink> LinksInternal { get; set; }
   public virtual IReadOnlyList<NodeLink> Links
   {
     get { return LinksInternal.ToList(); }
   } 

   protected MongoNode()
   {
     LinksInternal = new HashSet<NodeLink>();
   } 

   public MongoNode(string name)
     : this()
   {
     Name = name;
   } 

   public virtual void AddLink(MongoNode mongoNode)
   {
     LinksInternal.Add(new NodeLink(mongoNode.Id, mongoNode.Name));
     mongoNode.LinksInternal.Add(new NodeLink(Id, Name));
   }
 }
public class MongoNodeMap : ClassMap<MongoNode> //FluentNHibernate中的类继承
  {
    public MongoNodeMap()
    {
      Id(x => x.Id, "MongoNodeId").GeneratedBy.HiLo("[dbo].[Ids]", "NextHigh", "10", "EntityName = 'MongoNode'");
      Map(x => x.Name).Not.Nullable();
    }
  }

Utils层的类:
EventListener.cs内容:

internal class EventListener : IPostLoadEventListener //NHibernate.Event继承
  {
    public void OnPostLoad(PostLoadEvent ev)
    {
      var networkNode = ev.Entity as MongoNode; 

      if (networkNode == null)
        return; 

      var repository = new NodeLinkRepository();
      IList<NodeLink> linksFromMongo = repository.GetLinks(networkNode.Id); 

      HashSet<NodeLink> links = (HashSet<NodeLink>)networkNode
        .GetType()
        .GetProperty("LinksInternal", BindingFlags.NonPublic | BindingFlags.Instance)
        .GetValue(networkNode);
      links.UnionWith(linksFromMongo);
    }
  }
internal class Interceptor : EmptyInterceptor //NHibernate中的类
 {
   public override void PostFlush(ICollection entities)
   {
     IEnumerable<MongoNode> nodes = entities.OfType<MongoNode>(); 

     if (!nodes.Any())
       return; 

     var repository = new NodeLinkRepository();
     Task[] tasks = nodes.Select(x => repository.SaveLinks(x.Id, x.Links)).ToArray();
     Task.WaitAll(tasks);
   }
 }

UnitOfWork.cs代码:

public class UnitOfWork : IDisposable
 {
   private readonly ISession _session;
   private readonly ITransaction _transaction;
   private bool _isAlive = true;
   private bool _isCommitted; 

   public UnitOfWork()
   {
     _session = SessionFactory.OpenSession();
     _transaction = _session.BeginTransaction(IsolationLevel.ReadCommitted);
   } 

   public void Dispose()
   {
     if (!_isAlive)
       return; 

     _isAlive = false; 

     try
     {
       if (_isCommitted)
       {
         _transaction.Commit();
       }
     }
     finally
     {
       _transaction.Dispose();
       _session.Dispose();
     }
   } 

   public void Commit()
   {
     if (!_isAlive)
       return; 

     _isCommitted = true;
   } 

   internal T Get<T>(int id)
   {
     return _session.Get<T>(id);
   } 

   internal void SaveOrUpdate<T>(T entity)
   {
     _session.SaveOrUpdate(entity);
   } 

   internal IQueryable<T> Query<T>()
   {
     return _session.Query<T>();
   }
 }

Database.sql建表语句:

CREATE DATABASE [SqlWithMongo]
GO
USE [SqlWithMongo]
GO
/****** 表 [dbo].[Ids] ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Ids](
  [EntityName] [nvarchar](100) NOT NULL,
  [NextHigh] [int] NOT NULL,
 CONSTRAINT [PK_Ids] PRIMARY KEY CLUSTERED
(
  [EntityName] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] 

GO
/****** 表 [dbo].[MongoNode] ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[MongoNode](
  [MongoNodeId] [int] NOT NULL,
  [Name] [nvarchar](100) NOT NULL,
 CONSTRAINT [PK_MongoNode] PRIMARY KEY CLUSTERED
(
  [MongoNodeId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] 

GO
/****** 表 [dbo].[Node] ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Node](
  [NodeId] [int] NOT NULL,
  [Name] [nvarchar](100) NOT NULL,
 CONSTRAINT [PK_NetworkNode] PRIMARY KEY CLUSTERED
(
  [NodeId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] 

GO
/****** 表 [dbo].[Node_Node] ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Node_Node](
  [NodeId1] [int] NOT NULL,
  [NodeId2] [int] NOT NULL,
 CONSTRAINT [PK_NetworkNode_NetworkNode] PRIMARY KEY CLUSTERED
(
  [NodeId1] ASC,
  [NodeId2] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] 

GO
ALTER TABLE [dbo].[Node_Node] WITH CHECK ADD CONSTRAINT [FK_NetworkNode_NetworkNode_NetworkNode] FOREIGN KEY([NodeId1])
REFERENCES [dbo].[Node] ([NodeId])
GO
ALTER TABLE [dbo].[Node_Node] CHECK CONSTRAINT [FK_NetworkNode_NetworkNode_NetworkNode]
GO
ALTER TABLE [dbo].[Node_Node] WITH CHECK ADD CONSTRAINT [FK_NetworkNode_NetworkNode_NetworkNode1] FOREIGN KEY([NodeId2])
REFERENCES [dbo].[Node] ([NodeId])
GO
ALTER TABLE [dbo].[Node_Node] CHECK CONSTRAINT [FK_NetworkNode_NetworkNode_NetworkNode1]
GO 

INSERT dbo.Ids (EntityName, NextHigh)
VALUES ('MongoNode', 0)
INSERT dbo.Ids (EntityName, NextHigh)
VALUES ('Node', 0)

结果如图:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • SQL Server 日期函数CAST 和 CONVERT 以及在业务中的使用介绍

    最近时间刚从客户端转入后台写服务,对于后台数据库以及服务的书写完全是个小白,所以最近写的肯定没有太多技术含量. 首先把遇到的问题摆出来:还是那张错误上报表,字段主要有上报错误ID(ErrorID),上报人(ReportPerson),上报时间(ReportTime)精确到毫秒,现在要做的统计是:(1)统计一定时间内[起止时间精确到毫秒](beginTime,endTime)每个人每天上报的错误个数(2)统计一定时间内[起止时间到精确到月](beginTime,endTime)按月统计每个人上报的

  • SqlServer高版本数据备份还原到低版本

    最近遇见一个问题: 想要将Sqlserver高版本备份的数据还原到低版本SqlServer上去,但是这在SqlServer中是没法直接还原数据库的,所以经过一系列的请教总结出来一下可用方法. 首先.你得在电脑上装有你将要操作的高版本以及低版本的SqlServer或者你能够连上SqlServer高版本所在的数据库(便于后面拷贝数据), 第二步.打开高版本数据库中你需要备份的数据库,将你备份的数据库相关的登录名或者用户删除.右键数据库->任务->生成脚本.在生成脚本的"选择对象"

  • SQL Server 2012 安装与启动图文教程

    本文给大家介绍sql server2012安装与启动图文教程,非常详细. sqlserver2012安装步骤如下所示: SQL Server 2012 安装过程很漫长, 里面很多界面不一一截取了,我分别在win7 企业版 64位 和 win10专业版SP1 64位 装了SQL Server 2012 ,都没有问题. 1. 安装的功能选择,选择"全部" 2. 数据库引擎设置,选择"混合模式",给系统管理员sa设定登录密码. 如果你在安装的时候选择的是windows登录

  • SQL SERVER中强制类型转换cast和convert的区别详解

    SQL SERVER中强制类型转换cast和convert的区别 在SQL SERVER中,cast和convert函数都可用于类型转换,其功能是相同的, 只是语法不同. cast一般更容易使用,convert的优点是可以格式化日期和数值. select CAST('123' as int) -- 123 select CONVERT(int, '123') -- 123 select CAST(123.4 as int) -- 123 select CONVERT(int, 123.4) --

  • Sql Server 2012 转换函数的比较(Cast、Convert和Parse)

    语法结构: 1. Cast 语法结构:CAST ( expression AS data_type [ ( length ) ] ) 2. Convert 语法结构:CONVERT ( data_type [ ( length ) ] , expression [ , style ] ) 3. Parse 语法结构:PARSE ( string_value AS data_type [ USING culture ] ) 其中,Parse 为 Sql Server 的新特性 expression

  • mysql启动报错MySQL server PID file could not be found

    昨天解决完数据库跨权限操作后,今天打开项目突然报错了,然后重启数据库时,报 ERROR! MySQL server PID file could not be found!,命令行链接数据库时也报 Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2),网上找了一些资料,居然都是相互抄袭的,并且并没有解决问题.然后自己摸索了一下,问题就解决了,下面是我的解决方案,以便和我一样遇到问题的童

  • CentOS安装SQL Server vNext CTP1教程

    今天微软正式发布上SQL Server 2016 SP1,根据以往的SP1定律,可以在生产环境上使用了.打了SP1的标准版将具有企业版几乎所有的的功能.只有RAM 超过128GB或者超过24核心或者超过4路的环境才必须要安装企业版. 还有一个重要的发布:SQL Server vNext on Linux.也是本文介绍安装的版本.长话短说,开始安装. 这个版本的SQL Server,官方支持的平台是Red Hat Enterpise 7.2 或者Ubuntu 16.04.但是我手上暂时没有Red

  • SQL server中字符串逗号分隔函数分享

    继SQl -Function创建函数数据库输出的结果用逗号隔开,在开发中也有许多以参数的形式传入带逗号字条串参数(数据大时不建议这样做) 例:查找姓名为"张三,李二" 的数据此时在数据库里就要对此参数做处理如图: 函数代码如下 CREATE FUNCTION [dbo].[fnSplitStr] ( @sText NVARCHAR(Max), @sDelim CHAR(1) ) RETURNS @retArray TABLE ( value VARCHAR(100) ) AS BEGI

  • sqlserver四舍五入使用round函数及cast和convert函数

    引言 今天和测试沟通一个百分比计算方式时遇到一个问题, 我在存储过程里用到了强转CAST(32.678 AS DECIMAL(5,1))  我认为该方式只会保留一位小数,我给测试的回复是我并没有用到四舍五入函数,数据也没有四舍五入,而测试说他们自己验证后觉的数据是经过四舍五入了的. 想到这里于是我再试了试存储过程的每个计算点,才发现了这个问题. ROUND 那么用到四舍五入并且保留小数点时我们肯定会首选ROUND函数,  如果字段的数据类型是decimal(18,10)时那么四舍五入后还会有很多

  • SQL Server配置管理器无法连接到WMI提供程序

    今天在打开sql server 的时候打不开.报了一个错误,然后我打开sql server配置管理器,就看到了如下图这个错误. 然后就去网上搜了这个问题的解决方法,综合起来有以下几种: 第一种: 给数据库程序network service读取权限即可. C:/Program Files/Microsoft SQL Server/90/Shared给这个目录增加network service权限或者user权限就可以了,当然你加Everyone也行. 这种方法我都不知道怎么操作,不会加. 第二种:

  • SQL Server 出现Error: 1326错误(管理器无法连接远程数据库)问题解决方案

    SQL Server 出现Error: 1326错误 我们在在使用SQL Server时都会遇到使用SQL Server Management Studio无法连接远程数据库实例的问题,错误描述信息摘录如下: An error has occurred while establishing a connection to the server. (provider: Named Pipes Provider, error: 40 – Could not open a connection to

随机推荐