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

回到顶部