通过将SqlServer与MongoDB结合使用NHibernate的方法

通过将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) 

结果如图:

通过将SqlServer与MongoDB结合使用NHibernate的方法

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