Моя команда заинтересована в переносе существующей базы данных MySQL (что бывает крайне уродливо и плохо проиндексировано) на OrientDB. Поскольку наше приложение написано на C#, я изучаю нашу возможность доступа к базе данных из приложения C#.OrientDB-NET.binary для моделей
Я нашел OrientDB-NET.binary как библиотеку, чтобы делать то, что хочу, однако у меня возникают проблемы с тем, чтобы сделать все, что я хочу. В базе данных я тестирую с очень просто, из документации OrientDB:
create class Person extends V
create class Car extends V
create class Country extends V
create class Owns extends E
create class Lives extends E
create property Owns.out LINK Person
create property Owns.in LINK Car
create property Lives.out LINK Person
create property Lives.in LINK Country
alter property Owns.out MANDATORY=true
alter property Owns.in MANDATORY=true
alter property Lives.out MANDATORY=true
alter property Lives.in MANDATORY=true
create index UniqueOwns on Owns(in) unique
create index UniqueLives on Lives(out) unique
Когда я запроса DB для ODocuments, я получаю много ожидаемой информации:
OClient.CreateDatabasePool("127.0.0.1", 2424, "cars",
ODatabaseType.Graph, "admin", "admin", 10, "Cars");
using (ODatabase db = new ODatabase("Cars"))
{
var results = db.Select().Form("Country").ToList();
foreach (var item in results)
{
foreach(var key in item.Keys)
{
Console.WriteLine(key);
if (item[key] is IEnumerable<ORID>)
{
foreach (var element in item[key] as IEnumerable<ORID>)
{
Console.WriteLine(" " + element);
}
}
else
{
Console.WriteLine(" " + item[key]);
}
}
Console.WriteLine();
}
}
Console.ReadKey();
Выход:
@ORID
#15:0
@OVersion
5
@OType
Document
@OClassId
0
@OClassName
Country
Name
UK
in_Lives
#16:0
@ORID
#15:1
@OVersion
3
@OType
Document
@OClassId
0
@OClassName
Country
Name
US
in_Lives
#16:1
#16:2
Если я создаю класс для представления своих вершин, я могу запросить для них:
public class Person
{
public string Name { get; set; }
}
public class Country
{
public string Name { get; set; }
}
public class Car
{
public string Name { get; set; }
}
//...
var results = db.Select().From("Country").ToList<Country>();
foreach (var item in results)
{
Console.WriteLine(item.Name);
}
Выход:
UK
US
Однако, я хочу, чтобы иметь возможность доступа к соединениям между моими вершинами:
public class Person
{
public string Name { get; set; }
public Country Lives { get; set; }
public IEnumerable<Car> Owns { get; set; }
}
public class Country
{
public string Name { get; set; }
public IEnumerable<Person> Lives { get; set; }
}
public class Car
{
public string Name { get; set; }
public Person Owns { get; set; }
}
Эти параметры не будут заполняться по запросу. Тем не менее, я могу добавить списки ORID для ребер:
public class Person
{
public string Name { get; set; }
public List<ORID> out_Lives { get; set; }
public List<ORID> out_Owns { get; set; }
}
public class Country
{
public string Name { get; set; }
public List<ORID> in_Lives { get; set; }
}
public class Car
{
public string Name { get; set; }
public List<ORID> in_Owns { get; set; }
}
Это не работает, если я просто пытаюсь запросить вершину:
db.Select().From("Person").ToList<Person>();
Различные части библиотеки, по-видимому, требующий различных типов на списки ребер. (Если я правильно помню, одна часть требует от них List
s, одна часть требует от них HashSet
s, а одна часть требует, чтобы у них был конструктор без параметров.) Но он работает, если я запрошу конкретные края:
db.Select("Name").As("Name")
.Also("out('Owns')").As("out_Owns")
.Also("out('Lives')").As("out_Lives")
.From("Person").ToList<Person>();
К сожалению, класс ORID
не содержит никакой информации, необходимой мне; это просто ссылка, которую я могу использовать в других запросах.
Мой последний оплот решение было попробовать создать регулировочные свойства, которые будут запрашивать базу данных на основе RID, просто чтобы увидеть, если я мог бы получить вещи работать:
public class Person
{
public string Name { get; set; }
public List<ORID> out_Owns { get; set; }
public List<ORID> out_Lives { get; set; }
public IEnumerable<Car> Owns
{
get
{
if (owns != null &&
out_Owns != null && owns.Count() == out_Owns.Count) return owns;
owns = new List<Car>();
if (out_Owns == null || out_Owns.Count == 0) return owns;
using (ODatabase db = new ODatabase("Cars"))
{
owns = db.Select("Name").As("Name")
.Also("in('Owns')").As("in_Owns")
.From(out_Owns.First()).ToList<Car>();
}
return owns;
}
}
public Country Lives
{
get
{
if (lives != null) return lives;
if (out_Lives == null || out_Lives.Count == 0) return null;
using (ODatabase db = new ODatabase("Cars"))
{
lives = db.Select("Name").As("Name")
.Also("in('Lives')").As("in_Lives")
.From(out_Lives.First()).ToList<Country>()
.FirstOrDefault();
}
}
}
private IEnumerable<Car> owns;
private Country lives;
}
public class Country
{
public string Name { get; set; }
public List<ORID> in_Lives { get; set; }
public IEnumerable<Person> Lives
{
get
{
if (lives != null &&
in_Lives != null && lives.Count() == in_Lives.Count) return lives;
lives = new List<Person>();
if (in_Lives == null || in_Lives.Count == 0) return lives;
using (ODatabase db = new ODatabase("Cars"))
{
StringBuilder sb = new StringBuilder();
foreach (ORID id in in_Lives)
{
sb.AppendFormat("{0},", id);
}
if (sb.Length > 0)
{
sb.Remove(sb.Length - 1, 1);
}
lives = db.Select("Name").As("Name")
.Also("out('Owns')").As("out_Owns")
.Also("out('Lives')").As("out_Lives")
.From(string.Format("[{0}]", sb)).ToList<Person>();
}
return lives;
}
}
private IEnumerable<Person> lives;
}
public class Car
{
public string Name { get; set; }
public List<ORID> in_Owns { get; set; }
public Person Owns
{
get
{
if (owns != null) return owns;
if (in_Owns == null || in_Owns.Count == 0) return null;
using (ODatabase db = new ODatabase("Cars"))
{
owns = db.Select("Name").As("Name")
.Also("out('Owns')").As("out_Owns")
.Also("out('Lives')").As("out_Lives")
.From(in_Owns.First()).ToList<Person>()
.FirstOrDefault();
}
}
}
private Person owns;
}
Эта функция, но она выглядит совершенно ужасный код. Я запрашиваю базу данных в моих аксессуарах get
(хотя кеширование результата несколько смягчает эту проблему) и делает это таким образом, что требует знания свойств связанных вершин, в средствах, которые невозможно поймать во время компиляции. Эти проблемы будут возрастать только по мере увеличения масштаба базы данных, как по количеству записей (одна из таблиц MySQL, в которую мы сейчас будем переносить более 7 миллионов строк), так и количество свойств (хотя, вероятно, это будет разбито на несколько классов , одна из таблиц MySQL имеет более 100 столбцов).
Я бы как, чтобы иметь возможность просто позвонить db.Select().From("MyVertex").ToList<MyVertex>();
и получить список MyVertex
объектов со свойствами для ребер, выходящих из вершины в графе. Возможно ли это с помощью этой библиотеки? Возможно ли это с любой C# library?
Официальный драйвер OrientDB .NET является: HTTPS: // GitHub. com/orientechnologies/OrientDB-NET.binary – Lvca
Я нашел это вчера. Это вилка репо, с которой я связан, и хотя это несколько коммитов впереди оригинала, для моего случая использования он выполняет одинаковые действия. –