本文使用的IDE是Visual Studio 2015 ,驱动程序是Neo4j官方的最新版本:Neo4j.Driver,创建的类库工程(Project)要求安装 .NET Framework 4.5.2及以上版本,Neo4j官方提供的驱动程序使用起来非常简单,非常依赖于Cypher语言,这使得该驱动程序能够处理很多任务,但是,官方驱动程序仅支持标量类型的参数(Parameters),由于Neo4j的批量更新,例如,Cypher语言的foreach,unwind命令等用于批量操作,非常依赖于参数,这也成了官方驱动最大的缺点。

一,安装Neo4j Driver

官方的.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#中引用驱动程序的命名空间:

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 for read 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 == ;
}
}

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 == ;
}
}

四,查询数据库

向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和.NET的类型映射

驱动程序把编程语言翻译成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[].As<string>()).ToList();
});
}
}

参考文档:

neo4j Driver Manual

3.2.4. Parameters

Nuget Neo4j Driver 1.3.0

Chapter 4. Drivers

Working with Cypher values

Neo4j 第四篇:使用C#更新和查询Neo4j的更多相关文章

  1. Neo4j 第四篇:使用.NET驱动访问Neo4j

    本文使用的IDE是Visual Studio 2015 ,驱动程序是Neo4j官方的最新版本:Neo4j.Driver,创建的类库工程(Project)要求安装 .NET Framework 4.5. ...

  2. Neo4j 第五篇:批量更新数据

    相比图形数据的查询,Neo4j更新图形数据的速度较慢,通常情况下,Neo4j更新数据的工作流程是:每次数据更新都会执行一次数据库连接,打开一个事务,在事务中更新数据.当数据量非常大时,这种做法非常耗时 ...

  3. Python之路【第十四篇】:AngularJS --暂无内容-待更新

    Python之路[第十四篇]:AngularJS --暂无内容-待更新

  4. ElasticSearch入门 第四篇:使用C#添加和更新文档

    这是ElasticSearch 2.4 版本系列的第四篇: ElasticSearch入门 第一篇:Windows下安装ElasticSearch ElasticSearch入门 第二篇:集群配置 E ...

  5. 从0开始搭建SQL Server AlwaysOn 第四篇(配置异地机房节点)

    从0开始搭建SQL Server AlwaysOn 第四篇(配置异地机房节点) 第一篇http://www.cnblogs.com/lyhabc/p/4678330.html第二篇http://www ...

  6. 第四篇 Entity Framework Plus 之 Batch Operations

    用 Entity Framework  进行 增,删,改.都是基于Model进行的,且Model都是有状态追踪的.这样Entity Framework才能正常增,删,改. 有时候,要根据某个字段,批量 ...

  7. 第十四篇 Integration Services:项目转换

    本篇文章是Integration Services系列的第十四篇,详细内容请参考原文. 简介在前一篇,我们查看了SSIS变量,变量配置和表达式管理动态值.在这一篇,我们使用SQL Server数据商业 ...

  8. 第四篇 Replication:事务复制-订阅服务器

    本篇文章是SQL Server Replication系列的第四篇,详细内容请参考原文. 订阅服务器就是复制发布项目的所有变更将传送到的服务器.每一个发布需要至少一个订阅,但是一个发布可以有多个订阅. ...

  9. 第四篇 Integration Services:增量加载-Updating Rows

    本篇文章是Integration Services系列的第四篇,详细内容请参考原文. 回顾增量加载记住,在SSIS增量加载有三个使用案例:1.New rows-add rows to the dest ...

随机推荐

  1. 如何在EF Core 使用存储过程

    使用EF Core框架能快速的帮助我们进行常规的数据处理和项目开发,但是ORM虽然好用,但是在许多复杂逻辑的数据处理时,我个人还是偏向用SQL和存储过程的方式去处理,但是研究了一下目前最新版本的EF ...

  2. python之绘制图形库turtle

    关于绘制图形库turtle# 画布上,默认有一个坐标原点为画布中心的坐标轴(0,0),默认"standard"模式坐标原点上有一只面朝x轴正方向小乌龟 一:海龟箭头Turtle相关 ...

  3. 【C语言】 8421BCD码与二进制的转换

    #define BCD2TODEC(bcd) (bcd) = ((bcd) & 0x0f)+ ((bcd)>>4)*10 #define BIN2BCD(bcd) (bcd) = ...

  4. C#程序如何捕捉未try/catch的异常——不弹“XXX已停止工作”报错框

    诚意满满直接上代码: static void Main(string[] args) { //Main函数中增加此句 AppDomain.CurrentDomain.UnhandledExceptio ...

  5. TiDB数据库集群安装以及注意事项

    今天尝试安装tidb集群.详细的安装步骤我们参考:https://pingcap.com/docs-cn/op-guide/ansible-deployment/ . 不过安装之前需要一些注意事项. ...

  6. spark-机器学习实践-K近邻应用实践一

    K近邻应用-异常检测应用 原理: 根据数据样本进行KMeans机器学习模型的建立,获取簇心点,以簇为单位,离簇心最远的第五个点的距离为阈值,大于这个值的为异常点,即获得数据异常. 如图:

  7. MySQL递归查询父节点或递归查询子节点-陈远波

    根据id查询父节点,具体需要修改的地方笔者已在注释中给大家作了注解 DELIMITER $$ USE `yjlc_platform`$$ -- getCompanyParent 为函数名 DROP F ...

  8. IDEA中的替换功能(替换代码中的变量名很好用哦)

    刚刚上班不久,这两天正在研究公司项目里面的代码,今天用阿里的插件扫描了一下代码,发现代码中有很多变量的命名,没有遵循驼峰式的命名规则.一开始我一个一个的修改这些变量名,后来无意中用了一下Ctrl+F( ...

  9. 利用ngx_python模块嵌入到Python脚本

    导读 Python是一种计算机程序设计语言.是一种动态的.面向对象的脚本语言,最初被设计用于编写自动化脚本(shell),随着版本的不断更新和语言新功能的添加,越来越多被用于独立的.大型项目的开发. ...

  10. 动态代理实现设置tomcat请求编码

    1)htmlcode: <html> <head> <title>$Title$</title> </head> <body> ...