简单的LINQ to SQL没有支持转换为SQL [英] simple linq to sql has no supported translation to SQL
问题描述
我有这个在我BlogRepository
公开的IQueryable< Subnus.MVC.Data.Model.Post> GetPosts()
{
VAR的查询=从p在db.Posts
让类别= GetCategoriesByPostId(p.PostId)
让评论= GetCommentsByPostId(p.PostId)
选择新Subnus.MVC.Data.Model.Post
{
分类=新LazyList<类别>(分类),
评论=新LazyList<注释>(评论),
PostId = p.PostId,
弹头= p.Slug,
标题= p.Title,
CreatedBy = p.CreatedBy,
CreatedOn = p.CreatedOn,
车身= p.Body
};
返回查询;
}
和
公开的IQueryable< Subnus.MVC.Data.Model.Comment> GetCommentsByPostId(INT postId)
{
VAR的查询=从C在db.Comments
其中,c.PostId == postId
选择新Subnus.MVC.Data.Model.Comment
{
车身= c.Body,
的EMail = c.EMail,
日期= c.CreatedOn,
网页= c.Website,
名称= c.Name
};
返回查询;
}
私人的IQueryable< Subnus.MVC.Data.Model.Category> GetCategoriesByPostId(INT postId)
{
VAR的查询=从C在db.Categories
加入PCM在db.Post_Category_Maps上c.CategoryId等于pcm.CategoryId
其中,pcm.PostId == postId
选择新Subnus.MVC.Data.Model.Category
{
的CategoryId = c.CategoryId,
名称= c.Name
};
返回查询;
}
当我aplly此过滤器
命名空间Subnus.MVC.Data
{
公共静态类BlogFilters
{
公共静态的IQueryable<邮政> WherePublicIs(这IQueryable的<邮政和GT; QRY,布尔州)
{
从对在QRY返回
其中,p.IsPublic ==状态
选择磷;
}
}
}
这一切都是在同一个命名空间,如果这种帮助的命名空间Subnus.MVC.Data P>
当我试图做到这一点
公共类BlogService:IBlogService
{
...
公众的IList<邮政> GetPublicPosts()
{
返回repository.GetPosts()WherePublicIs(真).ToList()。
}
...
}
这是命名空间Subnus.MVC.Service 它抛出错误
法System.Linq.IQueryable`1 [Subnus.MVC.Data.Model.Comment] GetCommentsByPostId(Int32)在没有支持转换为SQL。
正在调用 GetCommentsByPostId
中的哪些是最终的前pression树。那棵树,当 BlogService.GetPublicPosts
组成,被转换成SQL。
在此转换,它仅仅是一个方法调用,仅此而已。 LINQ to SQL的了解一定的方法调用,而你是不是其中之一。因此,错误。
从表面上看,这似乎像它应该工作。你写的可重复使用的查询和其他查询撰写他们。然而,你实际上说的是:在数据库服务器上每一行的处理过程中,调用此方法,它显然无法做到。事实上,它需要一个的IQueryable< T>
并返回的IQueryable< T>
并不能使它特别<。 / P>
想想这样说:你逝去的 postId
到 GetCategoriesByPostId
。直到你有你无法调用方法 postId
,而你没有其中的一个,直到你在查询服务器上。
您可能会需要定义共同防爆pression&LT;&GT;
的子查询实例,并使用这些组合物中。我没有想过这是什么会是什么样子,但它肯定是可行的。
编辑:
如果您更换
让类别= GetCategoriesByPostId(p.PostId)
让评论= GetCommentsByPostId(p.PostId)
...
分类=新LazyList&LT;类别&GT;(分类),
评论=新LazyList&LT;注释&GT;(评论),
与
分类=新LazyList&LT;类别&GT;(GetCategoriesByPostId(p.PostId)),
评论=新LazyList&LT;注释&GT;(GetCommentsByPostId(p.PostId)),
查询将不再抛出异常。
这是因为让
声明范围变量,在范围上的每一行。他们的必须来计算在服务器上。
预测,但是,让你把任意code的任务,然后同时建立在客户端上的执行结果。这意味着这两种方法将被调用,其每一个将发出其自己的查询。
i have this in my BlogRepository
public IQueryable<Subnus.MVC.Data.Model.Post> GetPosts()
{
var query = from p in db.Posts
let categories = GetCategoriesByPostId(p.PostId)
let comments = GetCommentsByPostId(p.PostId)
select new Subnus.MVC.Data.Model.Post
{
Categories = new LazyList<Category>(categories),
Comments = new LazyList<Comment>(comments),
PostId = p.PostId,
Slug = p.Slug,
Title = p.Title,
CreatedBy = p.CreatedBy,
CreatedOn = p.CreatedOn,
Body = p.Body
};
return query;
}
and
public IQueryable<Subnus.MVC.Data.Model.Comment> GetCommentsByPostId(int postId)
{
var query = from c in db.Comments
where c.PostId == postId
select new Subnus.MVC.Data.Model.Comment
{
Body = c.Body,
EMail = c.EMail,
Date = c.CreatedOn,
WebSite = c.Website,
Name = c.Name
};
return query;
}
private IQueryable<Subnus.MVC.Data.Model.Category> GetCategoriesByPostId(int postId)
{
var query = from c in db.Categories
join pcm in db.Post_Category_Maps on c.CategoryId equals pcm.CategoryId
where pcm.PostId == postId
select new Subnus.MVC.Data.Model.Category
{
CategoryId = c.CategoryId,
Name = c.Name
};
return query;
}
and when i aplly this filter
namespace Subnus.MVC.Data
{
public static class BlogFilters
{
public static IQueryable<Post> WherePublicIs(this IQueryable<Post> qry,bool state)
{
return from p in qry
where p.IsPublic == state
select p;
}
}
}
all this is in the same namespace if that help namespace Subnus.MVC.Data
when i try to do this
public class BlogService : IBlogService
{
...
public IList<Post> GetPublicPosts()
{
return repository.GetPosts().WherePublicIs(true).ToList();
}
...
}
that is in the namespace Subnus.MVC.Service it throws the error
Method 'System.Linq.IQueryable`1[Subnus.MVC.Data.Model.Comment] GetCommentsByPostId(Int32)' has no supported translation to SQL.
You are calling GetCommentsByPostId
within what is ultimately an expression tree. That tree, when composed in BlogService.GetPublicPosts
, is converted to SQL.
During that conversion, it is just a method call, nothing more. Linq to Sql understands certain method calls, and yours is not one of them. Hence the error.
On the surface, this seems like it should work. You write reusable queries and compose them from other queries. However, what you are actually saying is: "during the processing of each row on the database server, call this method", which it obviously can't do. The fact that it takes an IQueryable<T>
and returns an IQueryable<T>
does not make it special.
Think about it this way: you are passing postId
to GetCategoriesByPostId
. You can't call that method until you have a postId
, and you don't have one of those until you are on the server in the query.
You would probably need to define common Expression<>
instances for the sub-queries and use those in the composition. I haven't thought about what this would look like but it's certainly doable.
Edit:
If you replace
let categories = GetCategoriesByPostId(p.PostId)
let comments = GetCommentsByPostId(p.PostId)
...
Categories = new LazyList<Category>(categories),
Comments = new LazyList<Comment>(comments),
with
Categories = new LazyList<Category>(GetCategoriesByPostId(p.PostId)),
Comments = new LazyList<Comment>(GetCommentsByPostId(p.PostId)),
the query will no longer throw an exception.
This is because let
declares range variables, which are in scope for each row. They must be calculated on the server.
Projections, however, allow you to put arbitrary code in assignments, which is then executed while building results on the client. This means both methods will be called, each of which will issue its own query.
这篇关于简单的LINQ to SQL没有支持转换为SQL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!