有没有一种简单的方法可以从SQLite存储库中联接表
本文关键字:存储 SQLite 一种 方法 简单 有没有 | 更新日期: 2023-09-27 18:00:57
我正在开发一个程序来管理我的个人财务。我有一个存储所有数据的SQLite数据库,我可以加载/保存账户、账单、付款等。
我想做的是基于每个Payment
的PayeeId
加载关联帐户的帐户名。我知道如何使用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
属性,该属性链接到该Payment
的Payee
。Payment
本身不存储关于Payee
的任何其他信息,但我希望能够加载PayeeName
属性以与Payment
信息一起显示。有没有一种简单的方法可以做到这一点,或者我必须创建一个单独的ViewModel
来存储包含Payment
信息和Payee
信息的"混合"数据?
编辑
我知道我可以使用一个额外的类来实现这一点,例如PaymentInfo
或其他什么,并存储Payment
和Payee
数据,然后像这样访问它:PaymentInfo.Payment.PaymentAmount
或PaymentInfo.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
中
我没能找到一种使用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((调用上(我认为这应该生成一个单独的查询。