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 的全部内容, 来源链接: utcz.com/a/253607.html