gpt4 book ai didi

c# - 将 Linq2SQL 简单查询转换为 CompiledQueries 以提高应用程序性能

转载 作者:太空宇宙 更新时间:2023-11-03 22:00:59 26 4
gpt4 key购买 nike

我正在为 Windows Phone (SDK 7.1) 应用程序编写 Silverlight,我正在 LongListSelector 中显示来自 CompactSQL 数据库的数据。从 Silverlight Toolkit for Windows Phone 进行控制。

一旦列表长到大约 150 个项目,应用程序加载数据的速度就会真正变慢,页面之间的导航和动画无法显示(我知道使用后台线程有助于释放 UI 线程以用于动画)。

我目前有三个经常使用的查询 - 每次更新来自 LongListSelector 的数据或页面为 NavigatedTo 时。我已经转换了MoviesByTitle进入CompiledQuery这很有帮助,所以我希望对我的其他两个查询( groupedMoviesLongListSelector.ItemSource 类型为 List<Group<Movie>> )做同样的事情,但是我似乎无法找出正确的语法。

关于如何提高这些查询效率的任何建议 - 通过使用 CompiledQuery还是其他?

MoviesByTitle在另一个名为 Queries 的类中

public static Func<MovieDBContext, IOrderedQueryable<Movies>> MoviesByTitle = CompiledQuery.Compile((MovieDBContext db) => from m in db.Movies orderby m.Title,m.Year select m);

主页中的字段

private static List<String> characters = new List<String> { "#", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" };
public static List<Group<Movies>> emptyGroups = new List<Group<Movies>>();

在 MainPage 的 LoadDB() 方法内 - 在 OnNavigatedTo 和更新数据库时在其他几个地方调用此方法。

//Populates the 'empty' Groups of Movies objects only once.
if (emptyGroups.Count < 1)
{
characters.ForEach(x => emptyGroups.Add(new Group<Movies>(x, new List<Movies>())));
}

IEnumerable<Movies> query = Queries.MoviesByTitle(App.db);

//Groups the objects
IEnumerable<Group<Movies>> groupedMovies = (from t in query
group t by t.GroupHeader into grp
orderby grp.Key
select new Group<Movies>(grp.Key.ToString(), grp));

//Joins the 'empty' group and groupedMovies together for the LongListSelector control
moviesLongList.ItemsSource = (from t in groupedMovies.AsEnumerable().Union(emptyGroups)
orderby t.Title
select t).ToList();

GroupHeaderMovies 的属性和数据库中的一个实体

[Column(CanBeNull=true, UpdateCheck = UpdateCheck.Never)]
public char GroupHeader
{
get
{
char l;
//For Alphabetized Grouping, titles do NOT start with "The ..."
if (this.Title.ToLowerInvariant().StartsWith("the "))
{
l = this.Title.ToLowerInvariant()[4];
}
else
{
l = this.Title.ToLower()[0];
}
if (l >= 'a' && l <= 'z')
{
return l;
}
return '#';
}
set { }
}

Group类如下

public class Group<T> : IEnumerable<T>
{
public Group(string name, IEnumerable<T> items)
{
this.Title = name;
this.Items = new List<T>(items);
}

public string Title
{
get;
set;
}

public IList<T> Items
{
get;
set;
}
...
}

最佳答案

我假设 GroupHeader是存储在数据库中的实体,与 Movie 具有 1-n 关系实体。

首先,我在这里没有看到 3 个数据库查询。 LINQ 表达式并不总是数据库查询(例如,有 LINQ to Objects)。有时确定真正发生的事情是非常具有挑战性的。在这种情况下最好的 friend 是数据库分析器工具或 IntelliTrace - 它们显示运行时在数据库上执行的查询。

据我理解的代码,你实际上有 1+N查询:第一个是MoviesByTitle , 然后你有 N获取按标题分组的电影的表达式中的查询。这是N而不是 1因为你投了queryIEnumerable<>不再是一个查询,而是一个简单的 CLR 对象,它只是在 foreach 中迭代-like 每次需要 GroupHeader 时都会向数据库发送查询实体(这是一个实体,不是吗?)。

尝试将 2 个查询合并为一个。您甚至可能不需要使用 CompiledQuery .这是一个大概的代码:

// I left this without changes
if (emptyGroups.Count < 1)
{
characters.ForEach(x => emptyGroups.Add(new Group<Movies>(x, new List<Movies>())));
}

// I put var here, but it actually is an IQueryable<Movie>
var query = from m in App.db.Movies orderby m.Title, m.Year select m;

// Here var is IQueryable<anonymous type>, I just can't use anything else but var here
var groupedMoviesQuery = from t in query
group t by t.GroupHeader into grp
orderby grp.Key
select new
{
Movies = grp,
Header = grp.Key
};

// I use AsEnumerable to mark that what goes after AsEnumerable is to be executed on the client
IEnumerable<Group<Movie>> groupedMovies = groupedMoviesQuery.AsEnumerable()
.Select(x => new Group<Movie>(x.Header, x.Movies))
.ToList();

//No changes here
moviesLongList.ItemsSource = (from t in groupedMovies.AsEnumerable().Union(emptyGroups)
orderby t.Title
select t).ToList();

这段代码应该可以更好地工作。我实际上做的是我转了你的query来自 IEnumerable这是 IQueryable 的仅迭代 CLR 对象可以进一步包装成更复杂的查询。现在只有一个查询可以获取按标题分组的所有电影。它应该很快。

我会对代码进行更多改进,使其运行得更快:

  1. 您使用 Union从数据库中读取的实体和一些默认列表。你之后订购。您可以安全地从 Linq2Sql 代码中删除所有其他排序(“查询”和“groupedMoviesQuery”)
  2. 与连接相比,在这里分组似乎不是最有效的。你为什么不直接查询 GroupHeader包括他们的相关Movie秒?这应该会在数据库查询中生成 JOIN,这应该比 GROUP BY 更有效。
  3. 如果您仍然遇到性能问题,可以将查询转换为编译查询。

我将展示一个已编译查询的示例,用于优化上面列表的第一项的原始逻辑:

class Result
{
public GroupHeader Header {get;set;}
public IEnumerable<Movie> Movies {get;set;}
}

public static Func<MovieDBContext, IQueryable<Result>> GetGroupHeadersWithMovies =
CompiledQuery.Compile((MovieDBContext x) =>
from m in x.Movies
group m by m.GroupHeader into grp
select new Result
{
Movies = grp,
Header = grp.Key
});

关于c# - 将 Linq2SQL 简单查询转换为 CompiledQueries 以提高应用程序性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10135031/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com