iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 19
0
自我挑戰組

圖形資料庫是什麼,可以吃嗎 - Neo4j系列 第 19

Neo4j with C# 程式串接實作 part1 - 基本連接

前情提要

原本計畫是第 20 篇的時候才要進入這個主題的

不過前面那個章節寫到有點矇,可以能需要更多的準備時間才能把那些主題寫到更好

所以決定先擱置,先來寫些有把握的東西,也就是 Neo4j 該如何 C# 串接

為什麼選 C# 唯一原因:啊我工作就用 C# 啊

Install Package

首先拿出你的 Visual Studio 新建一個專案

在你要連接 Neo4j 前你要先裝官方提供的 Neo4j.Driver Package nuget 連結

裝好之後我們就可以開始建立基本的連接了

基本連線程式

先上個官網 For .NET 的連結

在開始寫基礎之前我們要先準備一個 Neo4j Server,參考第三~第五篇

再來你可以直接把官網提供的程式碼直接貼上去 ↓↓↓↓

public class HelloWorldExample : IDisposable
{
    private readonly IDriver _driver;

    public HelloWorldExample(string uri, string user, string password)
    {
        _driver = GraphDatabase.Driver(uri, AuthTokens.Basic(user, password));
    }

    public void PrintGreeting(string message)
    {
        using (var session = _driver.Session()) //這裡會錯
        {
            var greeting = session.WriteTransaction(tx =>  //這裡會錯
            {
                var result = tx.Run("CREATE (a:Greeting) " +  //這裡會錯
                                    "SET a.message = $message " +
                                    "RETURN a.message + ', from node ' + id(a)",
                    new {message});
                return result.Single()[0].As<string>();  //這裡也會錯
            });
            Console.WriteLine(greeting);
        }
    }

    public void Dispose()
    {
        _driver?.Dispose();
    }

    public static void Main()
    {
        using (var greeter = new HelloWorldExample("bolt://localhost:7687", "neo4j", "password"))
        {
            greeter.PrintGreeting("hello, world");
        }
    }
}

然後你就會發現它噴錯 (゚∀゚)

Neo4j.Driver 不知道在什麼時候,就已經移除了同步的寫法

可是官網居然完全沒跟上,到底 (゚∀゚;)

所以我們來稍微幫他修改一下吧

解析官方原始程式

我先把官方的原始程式拆成兩大塊

會噴錯的部分 & 不會噴錯的部分

我們先來看看不會錯的地方吧

public class HelloWorldExample : IDisposable
{
    private readonly IDriver _driver;

    public HelloWorldExample(string uri, string user, string password)
    {
        _driver = GraphDatabase.Driver(uri, AuthTokens.Basic(user, password));
    }

    public void Dispose()
    {
        _driver?.Dispose();
    }

    public static void Main()
    {
        using (var greeter = new HelloWorldExample("bolt://localhost:7687", "neo4j", "password"))
        {
            greeter.PrintGreeting("hello, world");
        }
    }
}

結構好像怪怪的,先改一下

嗯,這樣合理多了,順手換一下 class 名稱

public class Neo4jHandler : IDisposable
{
    //Neo4j連線基礎
    private readonly IDriver _driver;

    public Neo4jHandler(string uri, string user, string password)
    {
        //建立基礎連線
        _driver = GraphDatabase.Driver(uri, AuthTokens.Basic(user, password));
    }

    //繼承自 IDisposable
    public void Dispose()
    {
        _driver?.Dispose();
    }
}

class Program
{
    static void Main(string[] args)
    {
        //基本宣告,這個應該不用解釋
        using (var greeter = new Neo4jHandler("bolt://localhost:7687", "neo4j", "password"))
        {
            greeter.HelloWord("hello, world");
        }
    }
}

這個架構可以用,之後就這樣用了,接著來看看會噴錯的那段吧

public void PrintGreeting(string message)
{
    using (var session = _driver.Session())
    {
        var greeting = session.WriteTransaction(tx => 
        {
            var result = tx.Run("CREATE (a:Greeting) " +
                                "SET a.message = $message " +
                                "RETURN a.message + ', from node ' + id(a)",
                new { message });
            return result.Single()[0].As<string>();
        });
        Console.WriteLine(greeting);
    }
}

嗯~ 看起來有一段很明顯是 Cypher 的東西

所以翻譯一下這段,就是建立一個 Node 在讀回 Node 中的資料

OK,所以現在的問題是要如何執行一段 Cypher 以及回傳資料

讓我來改一下

//改法 1
public async Task<string> HelloWord(string message)
{
    string sql = $"CREATE (n:Greeting{{message:'{message}'}}) RETURN n.message + ' from node : '+ id(n)";
    
    //建立交談
    var session = _driver.AsyncSession();
    
    //開始交談
    var transaction = await session.BeginTransactionAsync();
    
    //執行 cypher 語法
    var echo = await transaction.RunAsync(sql);

    //取得回傳
    var result = await echo.ToListAsync(r => r[0].As<string>());
    
    //提交變更
    await transaction.CommitAsync();
    
    return result[0];
}

嗯,變了許多魔術呢

原本的那個結構改下去也不是不行

//改法 2
public async Task<string> HelloWord(string message)
{
    string sql = $"CREATE (n:Greeting{{message:'{message}'}}) RETURN n.message + ' from node : '+ id(n)";

    var session = _driver.AsyncSession();

    var greeting = await session.WriteTransactionAsync(async tx =>
        {
            var result = await tx.RunAsync(sql);
            return await result.ToListAsync(r => r[0].As<string>());
        });

    return greeting[0];
}

改法 1 跟改法 2 取得的結果會是一樣的,就看大家喜歡哪種寫法了

讓我們來看看執行的結果吧

看起來是好了,來進資料庫看看吧

這樣基本的串接測試就完成了


寫到 High 起來,才點無法收尾

今天簡單講了基本連接

之後的幾天會再來詳細講一些資料處理、格式轉換、或是一些應用之類的

這系列會寫幾篇我也不知道,預計是 4 篇

不過最近寫到後期計畫不斷的在調整

我也說不準w

下篇 Neo4j with C# 程式串接實作 part2 - 更多的資料讀寫實作

究竟鐵人賽能不能完賽呢,讓我們繼續看下去


My Source Code

Github Link

參考資料

Neo4j - Using Neo4j from .NET


排版好看的版本同步更新在我的 HackMD


上一篇
APOC Plugins - 一些小小的使用心得與開發經驗
下一篇
Neo4j with C# 程式串接實作 part2 - 更多的資料讀寫實作
系列文
圖形資料庫是什麼,可以吃嗎 - Neo4j30

尚未有邦友留言

立即登入留言