Не удалось получить элемент из SQLite.Net Async PCL

Я изо всех сил пытаюсь получить элемент по идентификатору, используя асинхронный API SQLite.Net Async PCL. Вот мой модельный класс

public class Invoice : IEntityBase
{
    public Invoice()
    {
        LineItems = new List<LineItem>();
        DateCreated = DateTime.Now;                
    }

    [PrimaryKey, AutoIncrement, Column("_id")]
    public int Id { get; set; }
    public DateTime DateCreated { get; set; }
    public int Term { get; set; }
    public bool Paid { get; set; }
    public decimal Total { get; set; }
    public string Notes { get; set; }

    [OneToMany(CascadeOperations = CascadeOperation.All)] 
    public List<LineItem> LineItems { get; set; }    

}

И LineItems, которые имеют здесь отношение «один ко многим»

[PrimaryKey, AutoIncrement, Column("_id")]
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public string Category { get; set; }
public int Qty { get; set; }

[ForeignKey(typeof(Invoice))]
public int InvoiceId { get; set; }

[ManyToOne]
public Invoice Invoice { get; set; }

Вот конструктор:

public SQLiteAsyncConnection DbConnection;

public InvoiceDatabase(ISQLitePlatform platform, string databasePath)
{
    if (DbConnection == null)
    {
        var connectionAsync = new Func<SQLiteConnectionWithLock>(() =>
                new SQLiteConnectionWithLock
                    (
                        platform,
                        new SQLiteConnectionString(databasePath, false) 
                    )
                );
        DbConnection = new SQLiteAsyncConnection(connectionAsync);
        DbConnection.CreateTableAsync<Invoice>();                    
        DbConnection.CreateTableAsync<LineItem>();                                  
    }             
}

Другие методы CRUD (Insert, GetALL) работают, за исключением получения счета-фактуры по идентификатору, и Visual Studio и Xamarin Studio не дают мне никакой полезной трассировки стека.

Вот метод получения

private readonly InvoiceDatabase _database;

public InvoiceRepository(ISQLitePlatform platform, string databasePath)
{
    if (_database == null)
    {
        _database = new InvoiceDatabase(platform, databasePath);
    }
}

public async Task<Invoice> GetInvoice(int id)
{
    var result = await _database.DbConnection.Table<Invoice>()
                            .Where(t => t.Id == id)
                            .FirstOrDefaultAsync();
    return result;
}

Я передаю реализацию SQLite для Android, и, как я уже сказал, база данных создана, но я не могу вернуть объект Invoice, я даже пытался

public Task<Invoice> GetInvoiceWithChildren(int id)
{
    return _database.DbConnection.GetWithChildrenAsync<Invoice>(id);
}

Любая помощь будет оценена.


person Val Okafor    schedule 24.03.2015    source источник
comment
Ваш вопрос сбивает с толку. Вы заявляете, что пробовали два разных конструктора, но также говорите, что все остальные операции CRUD работают. Если операции CRUD работают, очевидно, что БД создается, поэтому проблема не в конструкторе. Вы получаете сообщение об ошибке при выполнении операции Get? Или он просто возвращает ноль?   -  person Jason    schedule 25.03.2015
comment
Я не соглашусь, что мой вопрос сбивает с толку. Я поделился шагами, которые я предпринял, и заявил, что у меня проблема только с получением элемента по идентификатору и что Visual Studio не дает мне никакой значимой ошибки. Спасибо за ваше время в любом случае.   -  person Val Okafor    schedule 25.03.2015


Ответы (1)


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

[OneToMany(CascadeOperations = CascadeOperation.All)] 
public List<LineItem> LineItems { get; set; }  

Я пропустил часть документации, в которой повторяется тот факт, что SQLite.Net является облегченной ORM - этот момент нельзя было подчеркнуть достаточно, поэтому вам придется удалить полноразмерные шляпы ORM, такие как EF. Итак, после прочтения документации по расширению SQLite-Net, в которой говорится

Свойства текстовых выделений Свойства текстовых выделений сериализуются в текстовые свойства при сохранении и десериализуются при загрузке. Это позволяет хранить простые объекты в одной таблице в одном столбце. Свойства текстовых BLOB-объектов имеют небольшие накладные расходы на сериализацию и десериализацию объектов и некоторые ограничения, но это лучший способ хранения простых объектов, таких как List или Dictionary, базовых типов или простых отношений.

Я меняю свою собственность таким образом, и теперь все работает так, как ожидалось. Теперь перейдем к нюансам Async и Await.

[TextBlob("LineItemBlobbed")]
public List<LineItem> LineItems { get; set; }

public string LineItemBlobbed { get; set; }
person Val Okafor    schedule 27.03.2015