本文使用的IDE是Visual Studio 2015 ,驱动程序是Neo4j官方的最新版本:Neo4j.Driver ,建立的类库工程(Project)要求安装 .NET Framework 4.5.2及以上版本,Neo4j官方提供的驱动程序使用起来很是简单,很是依赖于Cypher语言,这使得该驱动程序可以处理不少任务,可是,官方驱动程序仅支持标量类型的参数(Parameters),因为Neo4j的批量更新,例如,Cypher语言的foreach,unwind命令等用于批量操做,很是依赖于参数,这也成了官方驱动最大的缺点。node
官方的.NET 驱动程序使用的是Blot协议,目前更新到1.72版本,依赖.NET Framework 4.5.2及以上版本数据库
1,依赖.NET Framework 4.6版本编程
建立Neo4jApp工程,配置工程的熟悉,设置目标架构(Target Framework)为.NET Framework 4.6缓存
2,安装驱动程序服务器
点击工具(Tools)菜单,经过NuGet Package Manager的控制台命令安装Neo4j的.NET驱动程序,选用1.3.0版本的缘由是项目较赶,暂时没有时间去学习最新的版本。网络
在C#中引用驱动程序的命名空间:session
using Neo4j.Driver.V1;
Neo4j驱动程序最核心的对象是:Driver对象,Session对象和Transaction对象。Driver对象用于链接数据库,Session对象用于建立事务,事务对象用于执行Cypher查询。事务只能在Read或Write模式下执行,因为Driver对象不会解析Cypher查询,它也不会检测到事务执行的是写,仍是读操做,所以,当一个写模式事务执行的是读操做,Neo4j数据库会抛出错误,执行失败。数据结构
Note that the driver does not parse Cypher and cannot determine whether a transaction is intended to carry out read or write operations. As a result of this, a
write
transaction tagged forread
will be sent to a read server, but will fail on execution.架构
1,链接数据库编程语言
Neo4j经过Driver对象来链接图形数据库,在建立Driver对象时,须要服务器的链接地址(即bolt监听地址,地址格式是"bolt://host:7687")和身份验证信息:user和password。
private readonly IDriver Driver; public Neo4jProviders(string uri, string user, string password) { Driver = GraphDatabase.Driver(uri, AuthTokens.Basic(user, password)); }
验证信息经过auth token来提供,基础验证是AuthTokens.Basic(user,password)。
2,建立会话(Session)
在链接图形数据库以后,建立会话,会话是一系列事务(Transaction)的容器,用于建立事务执行的上下文,也就是说,事务必须在session的上下文中执行。Neo4j驱动程序提供三种格式的事务,最简单的是自动提交事务模式,自动提交事务模式使用 Session对象的run()方法来实现。
示例代码以下,在建立Session以后,以自动提交模式执行事务,在数据库中建立一个节点,该节点具备标签和属性。
public void AddPerson(string name) { using (var session = Driver.Session()) { session.Run("CREATE (a:Person {name: $name})", new {name}); } }
在Neo4j的驱动程序中,发送到Neo4j数据库引擎的Cypher查询语句包含两部分:Query和Parameters,其中,Query是在数据库中执行的Cypher语句,Parameters是传递引擎的参数,在Query中以$para_name格式来引用参数,在Parameters中,参数的名词和$para_name中的para_name保持一致。
自动提交事务只包含一个Cypher语句,这意味着多个事务不能共享网络数据包,从而表现出比其余形式的事务更低的网络效率。自动提交事务旨在用于简单的用例,例如学习Cypher或编写一次性脚本时。 建议不要在生产环境中使用自动提交事务,或者在性能或弹性是主要问题时使用。
3,建立事务函数
事务函数是推荐的建立事务的方式,这种形式可以以最小的查询代码实现多个多个查询的输入,可以分离数据库查询和应用程序逻辑。
在Neo4j的事务中,读写操做都必须处于事务的上下文中。在Session对象中,当事务以自动提交模式执行(经过session.Run()函数调用)时,事务只包含一个Cypher语句,可是,这种模式有一个缺点,当Cypher语句执行失败时,事务不能从新执行(Replay)。Neo4j推荐使用事务函数模式,经过Session对象调用WriteTransaction()或 ReadTransaction()函数,并在事务函数包含事务单元,在事务执行失败时,可以在异常处理代码中从新执行Cypher语句。
public void AddPerson(string name) { using (var session = Driver.Session()) { session.WriteTransaction(tx => tx.Run("CREATE (a:Person {name: $name})", new {name})); } }
Cypher支持参数化查询,在Cypher语句中,使用参数替表明达式,实体的ID,参数不能用于关系类型和标签。在Neo4j数据库中,参数可以优化查询,使得Cypher的执行计划更容易被缓存,查询更快速。在Cypher中,经过$param引用参数。
1,使用参数建立节点
在执行事务以后,Session返回数据库执行的结果,经过result.Summary查看Cypher语句执行的结果。
public bool CreateSingleNode(string lable,string name) { string query = string.Format("CREATE (n:{0} ", lable)+ @"{name: $name})"; using (var session = Driver.Session(AccessMode.Write)) { var result = session.WriteTransaction(tx=>tx.Run(query, new { name })); IResultSummary rs = result.Summary; return rs.Counters.NodesCreated == 1; } }
2,使用参数建立关系
经过new建立匿名类型,参数名是匿名类型的字段,字段名必须和Cypher语句中的参数($para)保持一致。
public bool CreateRelationship(string RelationshipType,string SourceNodeName,string TargetNodeName) { string query = string.Format(@"match (n),(m) where n.name=$source and m.name=$target create (n)-[:{0}]->(m);",RelationshipType); using (var session = Driver.Session()) { var result = session.WriteTransaction(tx => tx.Run(query,new {source=SourceNodeName,target= TargetNodeName } )); IResultSummary rs = result.Summary; return rs.Counters.RelationshipsCreated == 1; } }
向Neo4j数据库发送请求,返回的是数据结构是一个表格,Title是return子句的投影的字段。
如示例图所示,查询返回的结构是表格(行-列)式的,列值主要分为两种,要么是节点的属性列表,以JSON结构显示,要么是标量值。
驱动程序的Session返回查询的结果,Keys字段是Cypher语句中return子句投影的字段列表;Values字段返回是查询结果。
public void MatchNodes(string lable, string name) { string query = string.Format(@"MATCH (n:{0} ", lable)+ @"{name: $name})-[r]->(m) RETURN n,id(n);"; using (var session = Driver.Session(AccessMode.Read)) { var result = session.ReadTransaction(rx => rx.Run(query, new { name })); //return 子句投影的字段列表 IReadOnlyList<string> keys = result.Keys; //查询返回的数据行 var rows = result.ToList(); foreach(var row in rows) { //每一个数据行都包含多个数据列 var columns = row.Values; foreach (var column in columns) { //每一个数据列,多是一个节点,也多是一个标量值 if(column.Key=="n") { var node = column.Value as INode; long NodeID = node.Id; string NodeLables = string.Join(",", node.Labels.ToArray()); foreach (var property in node.Properties) { string Property=string.Format("Property[Key:{0},Value:{1}", property.Key, property.Value); } } if(column.Key=="id(n)") { long NodeID=long.Parse(column.Value.ToString()); } } } } }
驱动程序把编程语言翻译成Cypher的类型系统,为了处理数据,须要了解编程语言的类型和Cypher的类型系统的映射。图的特有类型是:Node、Relationship和Path,基础类型:Boolean、Integer、Float、String、List、Map,对.NET的类型映射是:
语句执行的结果是由记录流(record stream)构成,结果一般由接收应用程序在到达时处理。一个记录是一个由Key/Value对构成的有序字典(Map),记录能够经过位置索引(0-based整数)和键(key,字符串)来访问。
例如,经过位置索引来选择记录:
public List<string> GetPeople() { using (var session = Driver.Session()) { //return session.ReadTransaction(tx => tx.Run("MATCH (a:Person) RETURN a.name AS name").ToList()); return session.ReadTransaction(tx => { var result = tx.Run("MATCH (a:Person) RETURN a.name ORDER BY a.name"); return result.Select(record => record[0].As<string>()).ToList(); }); } }
参考文档: