Skip to content

Commit f110b6f

Browse files
Hadi FadlallahHadi Fadlallah
Hadi Fadlallah
authored and
Hadi Fadlallah
committed
Created class library and demo application
1 parent bb32f31 commit f110b6f

File tree

9 files changed

+358
-0
lines changed

9 files changed

+358
-0
lines changed

SQLToNeo4j.sln

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 16
4+
VisualStudioVersion = 16.0.30204.135
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLToNeo4j", "SQLToNeo4j\SQLToNeo4j.csproj", "{9C598447-64FC-4A2A-BFC8-0AD7C22E06FB}"
7+
EndProject
8+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLToNeo4jDemo", "SQLToNeo4jDemo\SQLToNeo4jDemo.csproj", "{C6610976-D84D-49D9-93DD-450CFAAA4084}"
9+
EndProject
10+
Global
11+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
12+
Debug|Any CPU = Debug|Any CPU
13+
Release|Any CPU = Release|Any CPU
14+
EndGlobalSection
15+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
16+
{9C598447-64FC-4A2A-BFC8-0AD7C22E06FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17+
{9C598447-64FC-4A2A-BFC8-0AD7C22E06FB}.Debug|Any CPU.Build.0 = Debug|Any CPU
18+
{9C598447-64FC-4A2A-BFC8-0AD7C22E06FB}.Release|Any CPU.ActiveCfg = Release|Any CPU
19+
{9C598447-64FC-4A2A-BFC8-0AD7C22E06FB}.Release|Any CPU.Build.0 = Release|Any CPU
20+
{C6610976-D84D-49D9-93DD-450CFAAA4084}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21+
{C6610976-D84D-49D9-93DD-450CFAAA4084}.Debug|Any CPU.Build.0 = Debug|Any CPU
22+
{C6610976-D84D-49D9-93DD-450CFAAA4084}.Release|Any CPU.ActiveCfg = Release|Any CPU
23+
{C6610976-D84D-49D9-93DD-450CFAAA4084}.Release|Any CPU.Build.0 = Release|Any CPU
24+
EndGlobalSection
25+
GlobalSection(SolutionProperties) = preSolution
26+
HideSolutionNode = FALSE
27+
EndGlobalSection
28+
GlobalSection(ExtensibilityGlobals) = postSolution
29+
SolutionGuid = {7C7F7FA1-3635-489E-9060-09286BFE202B}
30+
EndGlobalSection
31+
EndGlobal

SQLToNeo4j/Column.cs

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+

2+
namespace SQLToNeo4j
3+
{
4+
public class Column
5+
{
6+
public string Name { get; set; }
7+
public string DataType { get; set; }
8+
public Column(string name, string type)
9+
{
10+
Name = name;
11+
DataType = type;
12+
}
13+
}
14+
}

SQLToNeo4j/Edge.cs

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+

2+
using System.Collections.Generic;
3+
4+
namespace SQLToNeo4j
5+
{
6+
public class Edge
7+
{
8+
public string ID { get; set; }
9+
public string Label { get; set; }
10+
public Dictionary<string, object> Properties { get; set; }
11+
public string FromNode { get; set; }
12+
public string FromNodeID { get; set; }
13+
public string ToNode { get; set; }
14+
public string ToNodeID { get; set; }
15+
public Edge(string id, string label, string from, string fromID, string to, string toID, Dictionary<string, object> properties = null)
16+
{
17+
ID = id;
18+
Label = label;
19+
FromNode = from;
20+
FromNodeID = fromID;
21+
ToNodeID = toID;
22+
ToNode = to;
23+
if (properties != null)
24+
Properties = properties;
25+
else
26+
Properties = new Dictionary<string, object>();
27+
}
28+
29+
}
30+
}

SQLToNeo4j/Neo4jWriter.cs

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Neo4jClient;
4+
5+
namespace SQLToNeo4j
6+
{
7+
public class Neo4jWriter : IDisposable
8+
{
9+
private GraphClient client;
10+
11+
public Neo4jWriter(Uri uri)
12+
{
13+
client = new GraphClient(uri);
14+
client.ConnectAsync().Wait();
15+
}
16+
17+
public void ImportNodes(List<Node> nodes)
18+
{
19+
foreach(Node nd in nodes)
20+
{
21+
string cypher =
22+
"(" + nd.Label + "_" + nd.ID.ToString() + ":" + nd.Label + " $prop)";
23+
client.Cypher.Create(cypher).WithParam("prop", nd.Properties).ExecuteWithoutResultsAsync().Wait(); ;
24+
}
25+
}
26+
27+
public void ImportEdges(List<Edge> edges)
28+
{
29+
foreach (Edge edg in edges)
30+
{
31+
Dictionary<string, object> param = new Dictionary<string, object>();
32+
param.Add("prop", edg.Properties);
33+
param.Add("id1", edg.FromNodeID);
34+
param.Add("id2", edg.ToNodeID);
35+
string cypher =
36+
"(" + edg.FromNode.ToLower() + "1" + ") -[:" + edg.Label + " $prop]->(" + edg.ToNode.ToLower() + "2" + ")";
37+
client.Cypher
38+
.Match("(" + edg.FromNode.ToLower() + "1:" + edg.FromNode + ")", "(" + edg.ToNode.ToLower() + "2:" + edg.ToNode + ")")
39+
.Where(edg.FromNode.ToLower() + "1.node_id = $id1")
40+
.AndWhere(edg.ToNode.ToLower() + "2.node_id = $id2")
41+
.Create(cypher)
42+
.WithParams(param).ExecuteWithoutResultsAsync().Wait(); ;
43+
}
44+
}
45+
46+
public void Dispose()
47+
{
48+
client.Dispose();
49+
}
50+
}
51+
}

SQLToNeo4j/Node.cs

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+

2+
using System.Collections.Generic;
3+
4+
namespace SQLToNeo4j
5+
{
6+
public class Node
7+
{
8+
public string ID { get; set; }
9+
public string Label { get; set; }
10+
public Dictionary<string,object> Properties { get; set; }
11+
public Node(string id, string label, Dictionary<string, object> properties = null)
12+
{
13+
ID = id;
14+
Label = label;
15+
16+
if (properties != null)
17+
Properties = properties;
18+
else
19+
Properties = new Dictionary<string, object>();
20+
}
21+
}
22+
}

SQLToNeo4j/SQLReader.cs

+164
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Data;
5+
using System.Data.SqlClient;
6+
7+
namespace SQLToNeo4j
8+
{
9+
public class SQLReader : IDisposable
10+
{
11+
public List<Node> Nodes { get; set; }
12+
public List<Edge> Edges { get; set; }
13+
public string ConnectionString { get; set; }
14+
15+
public SQLReader(string connection)
16+
{
17+
ConnectionString = connection;
18+
}
19+
public void GetNodes()
20+
{
21+
Nodes = new List<Node>();
22+
//initialize connection
23+
using (SqlConnection sqlcon = new SqlConnection(ConnectionString))
24+
{
25+
sqlcon.Open();
26+
//retrieving nodes tables
27+
using (SqlCommand sqlnodes = new SqlCommand("select name from sys.tables where is_node = 1", sqlcon))
28+
{
29+
SqlDataReader tablesreader;
30+
tablesreader = sqlnodes.ExecuteReader();
31+
32+
List<string> tables = new List<string>();
33+
34+
//get nodes tables
35+
while (tablesreader.Read())
36+
tables.Add(tablesreader[0].ToString());
37+
38+
tablesreader.Close();
39+
foreach (string tablename in tables)
40+
{
41+
//Get columns with data types
42+
string cmdColumns = String.Format("select column_name,data_type from information_schema.columns columns where table_name = '{0}'" +
43+
"and exists(select 1 from information_schema.columns temp where temp.column_name like 'graph_id_%'" +
44+
"and temp.TABLE_SCHEMA = columns.table_schema and temp.TABLE_NAME = columns.TABLE_NAME)", tablename);
45+
List<Column> columns = new List<Column>();
46+
using (SqlCommand sqlcmd = new SqlCommand(cmdColumns, sqlcon))
47+
{
48+
SqlDataReader columnsreader = sqlcmd.ExecuteReader();
49+
while (columnsreader.Read())
50+
{
51+
columns.Add(new Column(columnsreader[0].ToString(), columnsreader[1].ToString()));
52+
}
53+
columnsreader.Close();
54+
}
55+
56+
string idcolumn = columns.Where(x => x.Name.StartsWith("$node_id")).FirstOrDefault().Name;
57+
string propColumns = string.Join(",", columns.Select(x => x.Name).Where(y => !y.StartsWith("$") && !y.StartsWith("graph_id_")));
58+
string cmdNodes = "select JSON_VALUE([" + idcolumn + "],'$.id') as node_id "
59+
+ (propColumns == "" ? "" : "," + propColumns);
60+
cmdNodes = cmdNodes + string.Format(" from {0}", tablename);
61+
//get nodes
62+
using (SqlCommand sqlcmd = new SqlCommand(cmdNodes, sqlcon))
63+
{
64+
SqlDataReader nodesreader = sqlcmd.ExecuteReader();
65+
//Get properties
66+
67+
while (nodesreader.Read())
68+
{
69+
Dictionary<string, object> properties = new Dictionary<string, object>();
70+
foreach (Column col in columns.Where(x => !x.Name.StartsWith("$") && !x.Name.StartsWith("graph_id_")))
71+
{
72+
properties.Add(col.Name, nodesreader[col.Name]);
73+
}
74+
properties.Add("node_id", nodesreader["node_id"].ToString());
75+
Nodes.Add(new Node(nodesreader["node_id"].ToString(), tablename, properties));
76+
}
77+
nodesreader.Close();
78+
}
79+
}
80+
}
81+
}
82+
}
83+
public void GetEdges()
84+
{
85+
Edges = new List<Edge>();
86+
//initialize connection
87+
using (SqlConnection sqlcon = new SqlConnection(ConnectionString))
88+
{
89+
sqlcon.Open();
90+
//retrieving nodes tables
91+
using (SqlCommand sqlnodes = new SqlCommand("select name from sys.tables where is_edge = 1", sqlcon))
92+
{
93+
SqlDataReader tablesreader;
94+
tablesreader = sqlnodes.ExecuteReader();
95+
96+
List<string> tables = new List<string>();
97+
98+
//get edges tables
99+
while (tablesreader.Read())
100+
tables.Add(tablesreader[0].ToString());
101+
102+
tablesreader.Close();
103+
foreach (string tablename in tables)
104+
{
105+
//Get columns with data types
106+
string cmdColumns = String.Format("select column_name,data_type from information_schema.columns columns where table_name = '{0}'" +
107+
"and exists(select 1 from information_schema.columns temp where temp.column_name like 'graph_id_%'" +
108+
"and temp.TABLE_SCHEMA = columns.table_schema and temp.TABLE_NAME = columns.TABLE_NAME)", tablename);
109+
List<Column> columns = new List<Column>();
110+
using (SqlCommand sqlcmd = new SqlCommand(cmdColumns, sqlcon))
111+
{
112+
SqlDataReader columnsreader = sqlcmd.ExecuteReader();
113+
while (columnsreader.Read())
114+
{
115+
columns.Add(new Column(columnsreader[0].ToString(), columnsreader[1].ToString()));
116+
}
117+
columnsreader.Close();
118+
}
119+
120+
string idcolumn = columns.Where(x => x.Name.StartsWith("$edge_id")).FirstOrDefault().Name;
121+
string fromid = columns.Where(x => x.Name.StartsWith("$from_id")).FirstOrDefault().Name;
122+
string toid = columns.Where(x => x.Name.StartsWith("$to_id")).FirstOrDefault().Name;
123+
string propColumns = string.Join(",", columns.Select(x => x.Name).Where(y => !y.StartsWith("$") && !y.StartsWith("graph_id_") && !y.StartsWith("from_") && !y.StartsWith("to_")));
124+
string cmdNodes = "select JSON_VALUE([" + idcolumn + "],'$.id') as edge_id " +
125+
",JSON_VALUE([" + fromid + "],'$.id') as from_id " +
126+
",JSON_VALUE([" + fromid + "],'$.table') as from_table " +
127+
",JSON_VALUE([" + toid + "],'$.id') as to_id " +
128+
",JSON_VALUE([" + toid + "],'$.table') as to_table" +
129+
(propColumns == "" ? "" : "," + propColumns);
130+
cmdNodes = cmdNodes + string.Format(" from {0}", tablename);
131+
132+
using (SqlCommand sqlcmd = new SqlCommand(cmdNodes, sqlcon))
133+
{
134+
SqlDataReader edgesreader = sqlcmd.ExecuteReader();
135+
//Get properties
136+
137+
while (edgesreader.Read())
138+
{
139+
Dictionary<string, object> properties = new Dictionary<string, object>();
140+
foreach (Column col in columns.Where(y => !y.Name.StartsWith("$") && !y.Name.StartsWith("graph_id_") && !y.Name.StartsWith("from_") && !y.Name.StartsWith("to_")))
141+
{
142+
properties.Add(col.Name, edgesreader[col.Name]);
143+
}
144+
Edges.Add(new Edge(edgesreader["edge_id"].ToString(), tablename,
145+
edgesreader["from_table"].ToString(), edgesreader["from_id"].ToString(),
146+
edgesreader["to_table"].ToString(), edgesreader["to_id"].ToString(), properties));
147+
}
148+
edgesreader.Close();
149+
}
150+
151+
}
152+
}
153+
}
154+
155+
}
156+
157+
public void Dispose()
158+
{
159+
Nodes = null;
160+
Edges = null;
161+
ConnectionString = null;
162+
}
163+
}
164+
}

SQLToNeo4j/SQLToNeo4j.csproj

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netcoreapp3.1</TargetFramework>
5+
</PropertyGroup>
6+
7+
<ItemGroup>
8+
<PackageReference Include="Neo4jClient" Version="4.0.3" />
9+
<PackageReference Include="System.Data.SqlClient" Version="4.8.2" />
10+
</ItemGroup>
11+
12+
</Project>

SQLToNeo4jDemo/Program.cs

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using System;
2+
using SQLToNeo4j;
3+
namespace SQLToNeo4jDemo
4+
{
5+
class Program
6+
{
7+
static void Main(string[] args)
8+
{
9+
using (SQLReader reader = new SQLReader("Server=<machine name>\\<instance name>;Database=GraphPL;Trusted_Connection=yes;"))
10+
{
11+
reader.GetNodes();
12+
reader.GetEdges();
13+
14+
using (Neo4jWriter importer = new Neo4jWriter(new Uri("http://<user>:<password>@localhost:7474")))
15+
{
16+
importer.ImportNodes(reader.Nodes);
17+
importer.ImportEdges(reader.Edges);
18+
}
19+
}
20+
}
21+
}
22+
}

SQLToNeo4jDemo/SQLToNeo4jDemo.csproj

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>netcoreapp3.1</TargetFramework>
6+
</PropertyGroup>
7+
8+
<ItemGroup>
9+
<ProjectReference Include="..\SQLToNeo4j\SQLToNeo4j.csproj" />
10+
</ItemGroup>
11+
12+
</Project>

0 commit comments

Comments
 (0)