考虑下面的完整代码块,特别是这部分 - 对象初始化(就是你所谓的那个?):
new LocalFileInfo() {
IsFavorite = p.IsFavorite,
...
WhenCrawled = p.WhenCrawled
}
有没有把这个代码抽象成一些我可以重用的方法,而不是将对象初始化代码复制粘贴到每个查询中?我强烈倾向于使用性能最佳的代码,而不是最容易维护的代码(但显然很容易维护)。
public static List<LocalFileInfo> RecentlyCrawledFiles(int take)
{
if (take < 1) take = 1;
List<LocalFileInfo> list = new List<LocalFileInfo>();
using (SQLite.Net.SQLiteConnection conn = new SQLite.Net.SQLiteConnection(new SQLite.Net.Platform.WinRT.SQLitePlatformWinRT(), sqliteDb))
{
// works but is slower.
// list = (from p in conn.Table<LocalFileInfo>() select p).OrderBy(f => f.WhenCrawled).Take(take).ToList();
list = (from p in conn.Table<LocalFileInfo>() select new LocalFileInfo() {
IsFavorite = p.IsFavorite,
LastModified = p.LastModified,
Name = p.Name,
ParentFolder = p.ParentFolder,
Path = p.Path,
Size = p.Size,
SourceId = p.SourceId,
SourceName = p.SourceName,
SourceType = p.SourceType,
WhenCrawled = p.WhenCrawled
})
.OrderByDescending(f => f.WhenCrawled)
.Take(take)
.ToList();
};
return list;
}
答案 0 :(得分:3)
该图书馆似乎忽略了您的预测,所以我不认为为他们制作表达会有任何帮助
例如,参见SqlLite.cs
TableQuery<T>
类
public IEnumerator<T> GetEnumerator ()
{
if (!_deferred)
return GenerateCommand("*").ExecuteQuery<T>().GetEnumerator();
return GenerateCommand("*").ExecuteDeferredQuery<T>().GetEnumerator();
}
每次执行GetEnumerator()
或ToList()
时都会使用此foreach (var item in query)
方法。
GenerateCommand()
将构建SQL,理论上它是#34;支持字符串参数selectList
,但库永远不会使用此参数
此外,当您执行Select(Expression)
时,libary会存储_selector
私有财产,但绝不会在GenerateCommand()
或任何其他呼叫
<强> This issue has been reported 强>
所以,我认为你最好的选择就是:
var list = conn.Table<LocalFileInfo>()
.OrderByDescending(f => f.WhenCrawled)
.Take(take)
.ToList();
此后您可以执行Select<T>()
,但该库已经加载了整个实体列表以及每个属性。但是,如果您保留这些实体(也就是说,ToList()
之后的预测不会立即给您带来任何好处),那么选择事后可以帮助您使用GC。
或者使用连接对象中的Query<T>()
...这将引导您返回SQL域。
或者,等待 Entity Framework Core to support Xamarin
Roadmap中提到了
Xamarin在某些情况下可以使用,但尚未作为受支持的方案进行全面测试。
很抱歉,但这是我现在能想到的最好的:(
编辑:事实上,我相信如果你做了Select(p => p.IsFavorite)
,那么图书馆会失败,因为它无法映射你的投影(不是抨击图书馆,只是抬头)
答案 1 :(得分:2)
而不是
var file = image.src; //this is the image url that i'm sending
怎么样:
list = (from p in conn.Table<LocalFileInfo>() select new LocalFileInfo() {
IsFavorite = p.IsFavorite,
LastModified = p.LastModified,
Name = p.Name,
ParentFolder = p.ParentFolder,
Path = p.Path,
Size = p.Size,
SourceId = p.SourceId,
SourceName = p.SourceName,
SourceType = p.SourceType,
WhenCrawled = p.WhenCrawled
})
只要您将所有属性投影到相同的对象类型中,它就会起作用。如果其中任何一个都不成立,那么你实际上可以像这样抽象出来:
list = conn.Table<LocalFileInfo>()
然后你可以这样称呼它:
public static class FromObjectExtensions
{
public static IEnumerable<ToObject> ToToObject(this IEnumerable<FromObject> q)
{
return q.Select(t=>new ToObject
{
Property1=t.Property1,
...
};
}
}
只需将list = conn.Table<LocalFileInfo>().ToToObject();
和ToObject
替换为您的实际对象类型,然后填写要复制的属性。
答案 2 :(得分:1)
这样做会很好。
using (SQLite.Net.SQLiteConnection conn = new SQLite.Net.SQLiteConnection(new SQLite.Net.Platform.WinRT.SQLitePlatformWinRT(), sqliteDb))
{
var list = conn.Table<LocalFileInfo>().OrderByDesending(f=>f.WhenCrawled).Take(take).ToList();
};
虽然您的查询有效,但您重新选择了一个没有意义的选定项目,特别是:
list = (from p in conn.Table<LocalFileInfo>() select new LocalFileInfo() {
IsFavorite = p.IsFavorite,
LastModified = p.LastModified,
Name = p.Name,
ParentFolder = p.ParentFolder,
Path = p.Path,
Size = p.Size,
SourceId = p.SourceId,
SourceName = p.SourceName,
SourceType = p.SourceType,
WhenCrawled = p.WhenCrawled
})
由于这是Linq,您首先收集对象,并重新创建已声明对象的新实例。这毫无意义,并且效率极低。
答案 3 :(得分:1)
您需要为选择器定义Expression
:
public static Expression<Func<LocalFileInfo, LocalFileInfo>> MyLocalFileInfoSelector =
p => new LocalFileInfo() {
IsFavorite = p.IsFavorite,
LastModified = p.LastModified,
Name = p.Name,
ParentFolder = p.ParentFolder,
Path = p.Path,
Size = p.Size,
SourceId = p.SourceId,
SourceName = p.SourceName,
SourceType = p.SourceType,
WhenCrawled = p.WhenCrawled
};
然后您可以在任何地方使用它:
return conn.Table<LocalFileInfo>()
.Select(MyLocalFileInfoSelector)
.OrderBy(f => f.WhenCrawled)
.Take(take)
.ToList();