有没有一种简单的方法可以从SQLite存储库中联接表

本文关键字:存储 SQLite 一种 方法 简单 有没有 | 更新日期: 2023-09-27 18:00:57

我正在开发一个程序来管理我的个人财务。我有一个存储所有数据的SQLite数据库,我可以加载/保存账户、账单、付款等。

我想做的是基于每个PaymentPayeeId加载关联帐户的帐户名。我知道如何使用SQL实现这一点,但我的数据是使用存储库设置的。例如,我通过调用加载Payments

var payments = await _paymentsRepository.LoadAllAsync();

LoadAllAsync()方法在RepositoryBase类中,看起来是这样的:

public async Task<IEnumerable<TTable>> LoadAllAsync()
{
    var query = _sqliteService.Conn.Table<TTable>();
    var array = (await query.ToListAsync()).ToArray();
    return array;
}

并在CCD_ 6接口中声明如下:

Task<IEnumerable<Payment>> LoadAllAsync();

每个Payment对象都有一个PayeeId属性,该属性链接到该PaymentPayeePayment本身不存储关于Payee的任何其他信息,但我希望能够加载PayeeName属性以与Payment信息一起显示。有没有一种简单的方法可以做到这一点,或者我必须创建一个单独的ViewModel来存储包含Payment信息和Payee信息的"混合"数据?

编辑

我知道我可以使用一个额外的类来实现这一点,例如PaymentInfo或其他什么,并存储PaymentPayee数据,然后像这样访问它:PaymentInfo.Payment.PaymentAmountPaymentInfo.Payee.PayeeName,但我必须在两个单独的查询中加载它们。虽然这当然是可能的,但我希望有一个可以在一个查询中完成的解决方案,这就是我考虑使用JOIN的原因。如果需要,我只会使用LINQ,但我的问题是,使用我目前拥有的存储库设置,这是否可行。

编辑2

这是存储库代码。我试图只包括相关的部分。每个表都有自己的存储库。这是PaymentsRepository:的签名

public class PaymentsRepository : RepositoryBase<Payment, int>, IPaymentsRepository
{
}

RepositoryBase<>看起来像这样:

public abstract class RepositoryBase<TTable, TKey> : IRepository<TTable, TKey>
       where TTable : IKeyedTable<TKey>, new()
{
    protected readonly ISqliteService SqliteService;
    protected RepositoryBase(ISqliteService sqlLiteService)
    {
        SqliteService = sqlLiteService;
    }
    public async Task<IEnumerable<TTable>> LoadAllAsync()
    {
        var query = SqliteService.Conn.Table<TTable>();
        var array = (await query.ToListAsync()).ToArray();
        return array;
    }
    ......
}

IRepository接口:

interface IRepository<TTable, in TKey>
 where TTable : IKeyedTable<TKey>, new()
{
    Task<TTable> LoadByIdAsync(TKey id);
    Task<IEnumerable<TTable>> LoadAllAsync();
    Task InsertAsync(TTable item);
    Task UpdateAsync(TTable item);
    Task DeleteAsync(TTable item);
    AsyncTableQuery<TTable> Query();
}

ISqliteService:

public interface ISqliteService
{
    SQLiteAsyncConnection Conn { get; }
    Task<object> ClearLocalDb();
    void Reconnect();
}

所有内容最终都会使用内置的SQLite方法针对SQLiteAsyncConnection属性进行查询。例如,在LoadAllAsync()函数中,var query = _sqliteService.Conn.Table<TTable>();使用以下内容:

public AsyncTableQuery<T> Table<T> ()
    where T : new ()
{
    //
    // This isn't async as the underlying connection doesn't go out to the database
    // until the query is performed. The Async methods are on the query iteself.
    //
    var conn = GetConnection ();
    return new AsyncTableQuery<T> (conn.Table<T> ());
}

位于SQLiteAsync.cs

有没有一种简单的方法可以从SQLite存储库中联接表

我没能找到一种使用LINQ直接查询两个不同表的方法,但我使用了一个"混合"类。我刚刚创建了一个PaymentInfo类,该类具有Payment属性和Payee属性,它们指向相关数据。我在PaymentsRepository中添加了一个方法,如下所示:

public async Task<IEnumerable<PaymentInfo>> LoadAllPaymentInfoAsync()
{
    var payments = await SqliteService.Conn.Table<Payment>().ToListAsync();
    var payees = await SqliteService.Conn.Table<Payee>().ToListAsync();
    var query = from p1 in payments
        join p2 in payees on p1.PayeeId equals p2.Id
        select new PaymentInfo() {Payment = p1, Payee = p2};
    return query;
}

我确信这不一定是实现这一目标的最佳方式,但我想我会在这里分享它,以防有人看到这个页面想要做我所做的事情。

我认为您可以获得IQueryable<Payment>IQueryable<Payee>,将它们加入LINQ,然后对结果调用.ToArray((。

它将构建查询,并仅在您实际访问数据时执行(在本例中,在ToArray((调用上(我认为这应该生成一个单独的查询。