有没有一种从 SQLite 存储库中加入表的简单方法?
Is there a simple way to JOIN tables from an SQLite repository?
我正在开发一个管理个人财务的程序。我有一个存储所有数据的 SQLite 数据库,我能够 load/save 账户、账单、付款等
我要做的是根据每个 Payment
的 PayeeId
加载关联帐户的帐户名称。我知道如何使用 SQL 实现此目的,但我的数据是使用存储库设置的。例如,我通过调用
加载 Payments
var payments = await _paymentsRepository.LoadAllAsync();
而 LoadAllAsync()
方法在 RepositoryBase
class 中,看起来像这样:
public async Task<IEnumerable<TTable>> LoadAllAsync()
{
var query = _sqliteService.Conn.Table<TTable>();
var array = (await query.ToListAsync()).ToArray();
return array;
}
并在 IPaymentsRepository
接口中声明如下:
Task<IEnumerable<Payment>> LoadAllAsync();
每个 Payment
对象都有一个 PayeeId
属性 链接到那个 Payment
的 Payee
。 Payment
本身不存储有关 Payee
的任何其他信息,但我希望能够加载 PayeeName
属性 以显示 Payment
信息。有没有一种简单的方法可以做到这一点,或者我必须创建一个单独的 ViewModel
来存储包含 Payment
信息和 Payee
信息的 "hybrid" 数据?
编辑
我知道我可以使用额外的 class 来完成此操作,例如 PaymentInfo
或其他东西,并存储 Payment
和 Payee
数据,然后访问它像这样:PaymentInfo.Payment.PaymentAmount
或 PaymentInfo.Payee.PayeeName
,但我必须在两个单独的查询中加载它们。虽然这当然是可能的,但我希望有一个可以在一个查询中完成的解决方案,这就是我考虑使用 JOIN
的原因。如果需要,我将只使用 LINQ,但我的问题是使用我当前拥有的存储库设置是否可行。
编辑 2
这是存储库代码。我试图只包括相关的部分。每个 table 都有自己的存储库。这是 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 直接查询两个不同表的方法,但我可以使用 "hybrid" class。我刚刚创建了一个 PaymentInfo
class,它有一个 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() 时)。 我相信这应该会生成一个查询。
我正在开发一个管理个人财务的程序。我有一个存储所有数据的 SQLite 数据库,我能够 load/save 账户、账单、付款等
我要做的是根据每个 Payment
的 PayeeId
加载关联帐户的帐户名称。我知道如何使用 SQL 实现此目的,但我的数据是使用存储库设置的。例如,我通过调用
Payments
var payments = await _paymentsRepository.LoadAllAsync();
而 LoadAllAsync()
方法在 RepositoryBase
class 中,看起来像这样:
public async Task<IEnumerable<TTable>> LoadAllAsync()
{
var query = _sqliteService.Conn.Table<TTable>();
var array = (await query.ToListAsync()).ToArray();
return array;
}
并在 IPaymentsRepository
接口中声明如下:
Task<IEnumerable<Payment>> LoadAllAsync();
每个 Payment
对象都有一个 PayeeId
属性 链接到那个 Payment
的 Payee
。 Payment
本身不存储有关 Payee
的任何其他信息,但我希望能够加载 PayeeName
属性 以显示 Payment
信息。有没有一种简单的方法可以做到这一点,或者我必须创建一个单独的 ViewModel
来存储包含 Payment
信息和 Payee
信息的 "hybrid" 数据?
编辑
我知道我可以使用额外的 class 来完成此操作,例如 PaymentInfo
或其他东西,并存储 Payment
和 Payee
数据,然后访问它像这样:PaymentInfo.Payment.PaymentAmount
或 PaymentInfo.Payee.PayeeName
,但我必须在两个单独的查询中加载它们。虽然这当然是可能的,但我希望有一个可以在一个查询中完成的解决方案,这就是我考虑使用 JOIN
的原因。如果需要,我将只使用 LINQ,但我的问题是使用我当前拥有的存储库设置是否可行。
编辑 2
这是存储库代码。我试图只包括相关的部分。每个 table 都有自己的存储库。这是 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 直接查询两个不同表的方法,但我可以使用 "hybrid" class。我刚刚创建了一个 PaymentInfo
class,它有一个 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() 时)。 我相信这应该会生成一个查询。