Как реализовать рекурсивную связь с расширениями SQLite-Net

У меня есть таблица Employee, которая должна иметь рекурсивное отношение, например.

Строка 1: EmployeeId = 1, EmployeeName = Альберт, SupervisorId = NULL;

Строка 2: EmployeeId = 2, EmployeeName = Leonardo, SupervisorId = 1;

т. е. EmployeeId(2) является дочерним элементом EmployeeId(1)

У меня есть следующий код на C#, в котором я использую SQLite-Net Extentions для реализации рекурсивная связь:

public class Employee
{
    public Employee()
    {
        Subordinates = new List<Employee>();
    }

    [PrimaryKey]
    [MaxLength(36)]
    public string EmployeeGuid { get; set; }

    public string EmployeeName { get; set; }

    [OneToMany("SupervisorGuid")]
    public List<Employee> Subordinates { get; set; }

    [ManyToOne("EmployeeGuid")]
    public Employee Supervisor { get; set; }

    [ForeignKey(typeof(Employee))]
    [MaxLength(36)]
    public string SupervisorGuid { get; set; }
}

Затем я тестирую код — создаю двух сотрудников и добавляю их в таблицу Employee:

Первый сотрудник

Employee employee1 = new Employee
{
    EmployeeGuid = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
    EmployeeName = "Albert"
};

Insert(employee1);

Второй сотрудник

Employee employee2 = new Employee
{
    EmployeeGuid = "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb",
    EmployeeName = "Leonardo",
    SupervisorGuid = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
};

Insert(employee2);

НО когда я звоню

GetByGuid(string guid) 

с guid, принадлежащим 1-му сотруднику, я получаю следующую ошибку:

Дополнительная информация: Объект типа Project.Models.Employee нельзя преобразовать в тип System.Collections.Generic.List`1.

Поддерживает ли SQLite-Net рекурсивные отношения? Любые предложения, пожалуйста?

ОБНОВЛЕНИЕ

Код для GetByGuid():

public T GetByGuid(string guid)
{
    return Database.GetWithChildren<T>(guid);
}

Также, когда я добавляю 2-го сотрудника без указания внешнего ключа и выполняю вызов, он работает...


person MJ33    schedule 26.05.2014    source источник
comment
Можете ли вы показать код GetByGuid или это встроенный метод расширений SQLite?   -  person Christoph Fink    schedule 26.05.2014


Ответы (2)


В рекурсивных отношениях вы должны вручную указать обратные отношения, например:

public class Employee
{
    [PrimaryKey]
    [MaxLength(36)]
    public string EmployeeGuid { get; set; }

    public string EmployeeName { get; set; }

    [OneToMany(inverseProperty: "Supervisor")]
    public List<Employee> Subordinates { get; set; }

    [ManyToOne(inverseProperty: "Subordinates")]
    public Employee Supervisor { get; set; }

    [ForeignKey(typeof(Employee))]
    [MaxLength(36)]
    public string SupervisorGuid { get; set; }
}

Я проверил это, и это работает, как и ожидалось. Однако я создал новую задачу в битбакете, потому что я думаю, что это поведение можно улучшить, поэтому этот случай будет работать в ближайшем будущем:

public class Employee
{
    [PrimaryKey]
    [MaxLength(36)]
    public string EmployeeGuid { get; set; }

    public string EmployeeName { get; set; }

    [OneToMany]
    public List<Employee> Subordinates { get; set; }

    [ManyToOne]
    public Employee Supervisor { get; set; }

    [ForeignKey(typeof(Employee))]
    [MaxLength(36)]
    public string SupervisorGuid { get; set; }
}

Надеюсь, поможет.

person redent84    schedule 01.08.2014

Кажется, GetWithChildren возвращает не T, а List<T>, поэтому вам нужно сделать, например:

public IEnumerable<T> GetByGuid(string guid)
{
    return Database.GetWithChildren<T>(guid);
}

или если вам нужен только элемент с предоставленным Guid:

public T GetByGuid(string guid)
{
    return Database.GetWithChildren<T>(guid)
               .FirstOrDefault(i => i.EmployeeGuid == guid);
}

Но тогда GetWithChildren, возможно, неправильный метод.

person Christoph Fink    schedule 26.05.2014
comment
GetWithChildren() может возвращать только один элемент, но он возвращает коллекцию, как вы заявили, поэтому я попытаюсь найти обходной путь - person MJ33; 26.05.2014
comment
Если это так, вы можете использовать Database.GetWithChildren<T>(guid).FirstOrDefault(). - person Christoph Fink; 26.05.2014