我有一张桌子:
-- Tag
ID | Name
-----------
1 | c#
2 | linq
3 | entity-framework
Run Code Online (Sandbox Code Playgroud)
我有一个类将有以下方法:
IEnumerable<Tag> GetAll();
IEnumerable<Tag> GetByName();
Run Code Online (Sandbox Code Playgroud)
在这种情况下我应该使用编译查询吗?
static readonly Func<Entities, IEnumerable<Tag>> AllTags =
CompiledQuery.Compile<Entities, IEnumerable<Tag>>
(
e => e.Tags
);
Run Code Online (Sandbox Code Playgroud)
然后我的GetByName方法是:
IEnumerable<Tag> GetByName(string name)
{
using (var db = new Entities())
{
return AllTags(db).Where(t => t.Name.Contains(name)).ToList();
}
}
Run Code Online (Sandbox Code Playgroud)
它生成SELECT ID, Name FROM Tag并执行Where代码.或者我应该避免CompiledQuery在这种情况下?
基本上我想知道何时应该使用编译查询.此外,在网站上,他们只为整个应用程序编译一次?
在实体框架(或linq-to-sql)中与SQL Server结合使用编译查询时,使用存储过程实际上是否仍有任何性能优势?
编译的查询将作为参数化查询进行缓存,因此性能应该接近存储过程.是否存在存储过程表现更好的情况?
- 编辑 -
为了回应下面的Yakimych的回答,我并不是要暗示编译的查询与存储过程相同.如果你在应用程序端完成所有可能的优化(在这种情况下是编译查询),我试图找出是否仍然需要sprocs.所以我想我正在寻找为什么存储过程比应用程序端优化和参数化查询(这是有效编译查询)的组合更好的原因.
我问这个的原因之一是因为有很多人似乎认为不再需要存储的程序因为不同的原因(即这篇文章).
我正在尝试通过缓存查询来提高Web应用程序的性能.
public static Func<myEntity, List<HASHDuplicates>, IQueryable<FormResponse>> CompiledDuplicatedResponses =
CompiledQuery.Compile<myEntity, List<HASHDuplicates>, IQueryable<FormResponse>>(
(db, hashes) => from r in db.FormResponse
from h in db.IndexHASHes
from d in hashes
where r.id == h.FormResponseID && h.IndexHASHString == d.hash
select r);
Run Code Online (Sandbox Code Playgroud)
我收到的错误是在编译时:
类型'myEntity'不能在泛型类型或方法'System.Data.Entity.Core.Objects.CompiledQuery.Compile(System.Linq.Expressions.Expression>)'中用作类型参数'TArg0'.没有从'myEntity'到'System.Data.Entity.Core.Objects.ObjectContext'的隐式引用转换.
我正在使用EF6
我想就此提出一些专家建议.我之前使用过编译查询,但对于这种特殊情况,我不确定它是否合适.
它是一个搜索表单,其中查询更改并依赖于正在搜索的内容.
static Func<DBContext, int, IQueryable<Foo>> Search = CompiledQuery.Compile(
(DBContext db, int ID) =>
db.Person
.Where(w => w.LocationID = ID)
.Select(s =>
new Foo
{
Name = s.PersonName,
Age = s.Age,
Location = s.LocationName,
Kin = s.Kin
}));
Run Code Online (Sandbox Code Playgroud)
现在如果有人填写搜索框,我想通过向查询添加另一个Where语句来扩展查询:
var query = Search(context, 123);
query = query.Where(w => w.Name.Contains(searchString));
Run Code Online (Sandbox Code Playgroud)
所以我的问题是,它将所有结果返回到哪里LocationID == 123,然后检查searchString匹配的结果?或者它实际上是否扩展了编译的查询?
如果它是前者(我怀疑它是),应该废弃CompiledQuery并只创建一个扩展查询的方法然后将其作为列表返回?
此外,最佳CompiledQuery使用方法是什么,是否有使用时间的指导原则?
注意:我在使用Linq to SQL的ASP.NET网站中使用上述内容.不确定这是否有所不同.
谢谢
我正在寻找有关已编译查询的执行的详细说明.我无法理解它们只是编译一次以及它们使用背后的优势
我有C#扩展方法IQueryable,例如FindNewCustomers(),FindCustomersRegisteredAfter(int year)依此类推,我用它来链接查询一起用于LINQ to SQL.
现在我的问题:我想创建编译查询,例如:
private static Func<MyDataContext, SearchInfo, IQueryable<Customer>>
CQFindAll =
CompiledQuery.Compile((MyDataContext dc, SearchInfo info) =>
dc.Contacts.Select(c => c).FindCustomersRegisteredAfter(info.RegYear)
.OrderBy(info.OrderInfo)
.Skip(info.SkipCount)
.Take(info.PageSize));
Run Code Online (Sandbox Code Playgroud)
FindCustomersRegisteredAfter(int year)方法是一种采用IQueryable并返回相同的扩展方法.该OrderBy方法也是一种扩展方法(System.Linq.Dynamic),它根据字符串创建动态表达式(例如"FirstName ASC"将对字段FirstName进行排序).Skip并且Take是内置方法.
上面(不是编译查询,但常规查询)工作完美.一旦我把它放在编译的查询中,我就会遇到以下错误:
方法 'System.Linq.IQueryable`1 [Domain.Customer] FindCustomersRegisteredAfter [客户](System.Linq.IQueryable`1 [Domain.Customer],Int32)将' 没有支持转换为SQL.
再次,如果查询是非编译的,只是常规的LINQ查询,这将完美地工作.只有在CompiledQuery.Compile()内部出现错误.
救命??!
编辑:如果我通过var query =(...)创建查询的方式与CompiledQuery.Compile内部相同,那么这就是生成的SQL:
SELECT [t1].[Id], [t1].[FirstName], [t1].[LastName],
[t1].[RegYear], [t1].[DeletedOn]
FROM (
SELECT ROW_NUMBER() OVER (ORDER BY [t0].[LastName]) AS [ROW_NUMBER],
[t0].[Id], [t0].[FirstName], [t0].[LastName], [t0].[RegYear], …Run Code Online (Sandbox Code Playgroud) 我正在创建一个委托来检索数据库中的所有专辑记录.我在另一个项目中使用了相同的方法,但由于某种原因我这次收到错误.
我错过了一步吗?我不确定为什么会出现这个错误.
码
public static readonly Func<CodySolutionEntities, IQueryable<Album>> SelectAlbums =
CompiledQuery.Compile<CodySolutionEntities, IQueryable<Album>>(
query => from q in query.Albums.Include("Photo")
select q);
Run Code Online (Sandbox Code Playgroud)
错误
错误1类型'CodyData.Diagram.CodySolutionEntities'不能用作类型 parameter 'TArg0' in the generic type or method 'System.Data.Objects.CompiledQuery.Compile<TArg0,TResult>(System.Linq.Expressions.Expression<System.Func<TArg0,TResult>>)'. There is no implicit reference conversion from 'CodyData.Diagram.CodySolutionEntities' to 'System.Data.Objects.ObjectContext'. C:\Users\Cody\Documents\CMBS\CodySolution\CodyData\Delegates\PhotoDelegates.cs 13 13 CodyData
在一个网站上,如果我有一个班级:
public class Provider
{
static readonly Func<Entities, IEnumerable<Tag>> AllTags =
CompiledQuery.Compile<Entities, IEnumerable<Tag>>
(
e => e.Tags
);
public IEnumerable<Tag> GetAll()
{
using (var db = new Entities())
{
return AllTags(db).ToList();
}
}
}
Run Code Online (Sandbox Code Playgroud)
在一个页面中我有:
protected void Page_Load(object sender, EventArgs ev)
{
(new Provider()).GetAll();
}
Run Code Online (Sandbox Code Playgroud)
查询将被编译多少次?每次页面加载......?一旦进入申请......?
我想在Entity Framework 6.1.3中优化我的查询,所以我需要知道查询是否已经是CompiledQueries还是我需要手动编写它们作为CompiledQuery?
提前致谢.
compiled-query ×10
c# ×8
linq ×4
linq-to-sql ×4
asp.net ×3
.net ×1
caching ×1
lifecycle ×1
scala ×1
slick ×1
sql-server ×1