Статьи

Neo4jD — .NET CLient для графической базы данных Neo4j — Часть 2

В этом посте рассказывается о некоторых новых функциях, добавленных в Neo4jD в последние дни.

Persist Статический типизированный объект

В предыдущем посте я объяснил, как создать Node и Relationship с помощью Neo4jD. Как вы могли заметить, свойства Node являются динамическими, например, чтобы задать FirstName, мы говорим «node.SetProperty (« FirstName »,« Sony »)». Как и я, большинству из нас не нравятся динамические свойства, поэтому мы создаем статические объекты. Этот пост посвящен тому, как сохранить статические объекты в Neo4j.

Примечание: я не против Dynamics, это просто личное предпочтение не строить вокруг Dynamics.

Давайте поговорим с некоторыми примерами.

public class Person
{
    public Person()
    {
        this.Address = new Address();
    }
    [EntityId]
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public Address Address { get; set; }
}

public class Address
{
    [EntityId]
    public int AddressId { get; set; }
    public string Address1 { get; set; }
    public string City { get; set; }
}

Итак, у меня есть два класса для хранения моих данных. Давайте посмотрим, как сохранить объект с помощью Neo4jD. Ядро Neo4jD основано на Node и Relationship с динамическими свойствами. Вдобавок к ядру я добавил маппер для сопоставления статических типизированных сущностей с узлами или связями. Я не собираюсь углубляться в понимание картографа, просто расскажу, например, если вам нужно больше понимания, лучше изучите Neo4jD в github .

Как сохранить объект

[TestCase]
public Person SaveTest()
{
    Person person = new Person { FirstName = "Sony", LastName= "Arouje"};
    NodeMapper mapper = new NodeMapper();
    person=mapper.Save<Person>(person);
    Console.WriteLine("Generated Id: " + person.Id.ToString());
    Assert.AreNotEqual(0, person.Id);
    return person;
}

За кулисами NodeMapper использует отражение, чтобы получить данные из объекта Person и создать объект Node. Посмотрим, как я это делаю.

public T Save<T>(T entity) where T:class
{
    Node node = this.CreateNode<T>(entity);
    node.Create();
    return MapperHelper.SetIdentity<T>(entity, node.Id);
}

private Node CreateNode<T>(T entity) where T:class
{
    Node node = new Node();
    node.AddProperty("clazz", typeof(T).ToString());
    typeof(T).GetProperties().Where(pr => pr.CanRead && MapperHelper.IsAnId(pr) == false)

    .ToList().ForEach(property =>
    {
        if(MapperHelper.IsPrimitive(property.PropertyType))
            node.AddProperty(property.Name, property.GetValue(entity, null).ToString());
    });

    return node;
}

Функция CreateNode выполняет сопоставление. Итерирует через свойство и вызывает node.AddProperty (property.Name, property.GetValue ()), это то же самое, что и node.AddProperty («FirstName», «Sony»).

Вы могли заметить, что поле Id в классе имеет атрибут EntityId. Это обязательный атрибут для получения или установки идентификатора узла в поле идентификатора объекта.

Получить экземпляр от Neo4J

[TestCase]
public void GetPersonById()
{
    NodeMapper mapper = new NodeMapper();
    Person person = mapper.Get<Person>(7);
    Console.WriteLine("Generated Id: " + person.Id.ToString());
    Assert.AreNotEqual(0, person.Id);
    Assert.AreEqual(“Sony”, person.FirstName);
}

Чтобы получить человека, которого я назвал mapper.Get с уникальным идентификатором человека, и картограф вернет действительного человека, если он существует в БД. NodeMapper использует нижеприведенную функцию для генерации объекта.

public T Get<T>(int id) where T:class
{
    Node node = Node.Get(id);
    T entity = (T)Activator.CreateInstance(typeof(T));
    if (node.GetProperty("clazz")!=typeof(T).ToString())
        throw new InvalidCastException(string.Format("Retrieved object with ID '{0}' is 

          an instance of '{1}' and unable to cast it to '{2}'", id.ToString(), 

          node.GetProperty("clazz"), typeof(T).ToString()));
    typeof(T).GetProperties().Where(pr => pr.CanRead && MapperHelper.IsAnId(pr) == false)

    .ToList().ForEach(property =>
    {
        property.SetValue(entity, MapperHelper.CastPropertyValue(property, 

        node.GetProperty(property.Name)), null);
    });

    entity = MapperHelper.SetIdentity<T>(entity, id);
    return entity;
}

 Создать отношения

Вы можете видеть, что Person имеет экземпляр Address, в Graph Person связан с Address. Давайте посмотрим, как мы можем создать это

[TestCase]
public void CanCreateRelationships()
{
    Person person = new Person { FirsName = "Sony", LastName = "Arouje" };
    person.Address.Address1 = "EcoSpace";
    person.Address.City = "Bangalore";
    NodeMapper mapper = new NodeMapper();
    mapper.CreateRelationshipTo<Person, Address>(person,person.Address);
    Console.WriteLine(person.Id.ToString());

    Assert.AreEqual(1, person.Id);
}

 

Функция CreateRelationShipTo будет сохранять как Персона, так и Адрес, если она не сохранена, иначе она создаст связь. В Neo4j отношения будут персона-> адрес.

Получить человека с отношениями

[TestCase]
public void CanGetRelatedNodes()
{
    NodeMapper mapper = new NodeMapper();
    Person person = mapper.Get<Person>(12);
    IList<Address> address = mapper.GetRelatedEntities<Person, Address>(person, typeof(Address));
    Assert.AreEqual(1, address.Count);
    Assert.AreEqual("EcoSpace", address[0].Address1);
}

Я знаю, что сохраняющиеся и извлекающие отношения немного запутаны, я буду работать над этим, чтобы сделать его более ясным и тихим.

Это все о сохранении статических объектов в Neo4j.

В следующем посте я расскажу о создании индекса, обхода с использованием Germlin и REST.