SqlServer與MongoDB結(jié)合使用NHibernate
本文實(shí)例為大家分享了SqlServer與MongoDB結(jié)合使用NHibernate的代碼,供大家參考,具體內(nèi)容如下
Program.cs代碼內(nèi)容:
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...");
//創(chuàng)建sqlserver的Node節(jié)點(diǎn)
CreateNodes();
Console.WriteLine("Completed");
Console.WriteLine("Linking nodes...");
long milliseconds1 = LinkSqlNodes(); //創(chuàng)建sqlserver的LinkNode節(jié)點(diǎn)
Console.WriteLine("SQL : " + milliseconds1);
long milliseconds2 = LinkMongoNodes(); //同時(shí)創(chuàng)建Node,LinkNode節(jié)點(diǎn)
Console.WriteLine("Mongo : " + milliseconds2);
Console.WriteLine("Completed");
Console.WriteLine("Fetching nodes...");
long milliseconds3 = FetchSqlNodes(); //取出sqlserver節(jié)點(diǎn)數(shù)據(jù)
Console.WriteLine("SQL : " + milliseconds3);
long milliseconds4 = FetchMongoNodes(); //取出Mongodb節(jié)點(diǎn)數(shù)據(jù)
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)); //實(shí)例化 構(gòu)造函數(shù)初始化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();
}
}
//清空數(shù)據(jù)
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();
}
}
}
相關(guān)輔助類代碼如下:
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)
{
//用編程的方式進(jìn)行配置,讓你能更好的理解,不需要編寫復(fù)雜的映射文件,它能完全替換NHibernate的映射文件,讓你在映射的時(shí)候能使用C#的強(qiáng)類型方式。
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 //倉(cāng)庫(kù) 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();
}
}
模型層數(shù)據(jù):
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內(nèi)容:
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建表語(yǔ)句:
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)
結(jié)果如圖:

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
MongoDB??數(shù)據(jù)模型的設(shè)計(jì)模式及優(yōu)缺點(diǎn)
這篇文章主要介紹了MongoDB??數(shù)據(jù)模型的設(shè)計(jì)模式,在實(shí)際開(kāi)發(fā)中,大多數(shù)性能問(wèn)題都可以追溯到糟糕的模型設(shè)計(jì),官方也提供分享過(guò)文檔模型設(shè)計(jì)的進(jìn)階技巧,這里簡(jiǎn)單翻譯記錄一下,需要的朋友可以參考下2022-12-12
在PyCharm中安裝Mongo Plugin的詳細(xì)教程
這篇文章主要介紹了在PyCharm中安裝Mongo Plugin的詳細(xì)教程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-11-11
Linux系統(tǒng)下安裝MongoDB的詳細(xì)方法圖文教程
這篇文章主要介紹了Linux系統(tǒng)下安裝MongoDB的詳細(xì)方法圖文教程,需要的朋友可以參考下2023-06-06
vs2019 下用 vb.net編寫窗體程序連接 mongodb4.2的方法
這篇文章主要介紹了vs2019 下用 vb.net編寫窗體程序連接 mongodb4.2,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-08
Mongodb實(shí)現(xiàn)的關(guān)聯(lián)表查詢功能【population方法】
這篇文章主要介紹了Mongodb實(shí)現(xiàn)的關(guān)聯(lián)表查詢功能,結(jié)合實(shí)例形式較為詳細(xì)的分析了population方法實(shí)現(xiàn)關(guān)聯(lián)表查詢的原理與相關(guān)操作技巧,需要的朋友可以參考下2017-07-07
MongoDB實(shí)現(xiàn)問(wèn)卷/考試設(shè)計(jì)功能
MongoDB是一個(gè)基于分布式文件存儲(chǔ)的數(shù)據(jù)庫(kù)。由C++語(yǔ)言編寫。旨在為WEB應(yīng)用提供可擴(kuò)展的高性能數(shù)據(jù)存儲(chǔ)解決方案。。本文給大家分享MongoDB實(shí)現(xiàn)問(wèn)卷/考試設(shè)計(jì),需要的朋友可以參考下2019-11-11
Ubuntu環(huán)境下mongodb安裝配置詳細(xì)步驟
大家好,本篇文章主要講的是Ubuntu環(huán)境下mongodb安裝配置詳細(xì)步驟,感興趣的同學(xué)快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽2021-11-11
記一次Mongodb中admin數(shù)據(jù)庫(kù)導(dǎo)致的事故
這篇文章主要給大家介紹了關(guān)于一次Mongodb中admin數(shù)據(jù)庫(kù)導(dǎo)致的事故的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2018-03-03
在mac系統(tǒng)下安裝與配置mongoDB數(shù)據(jù)庫(kù)
這篇文章主要介紹了在mac系統(tǒng)下安裝與配置mongoDB數(shù)據(jù)庫(kù)的操作步驟,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2021-09-09
Windows系統(tǒng)下安裝Mongodb 3.2.x的步驟詳解
mongodb3.x版本有好多新功能,關(guān)于這方面參考官網(wǎng)即可,下面這篇文章主要給大家介紹了在Windows系統(tǒng)下安裝Mongodb 3.2.x的詳細(xì)步驟,文中介紹的非常詳細(xì),需要的朋友們可以參考學(xué)習(xí),下面來(lái)一起看看吧。2017-03-03

