Nes*_*zer 22 .net linq-to-sql c#-3.0
我在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;
}
Run Code Online (Sandbox Code Playgroud)
和
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;
}
Run Code Online (Sandbox Code Playgroud)
当我适用这个过滤器
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;
}
}
Run Code Online (Sandbox Code Playgroud)
}
如果该帮助命名空间Subnus.MVC.Data,则所有这些都位于相同的命名空间中
当我尝试这样做
public class BlogService : IBlogService
{
...
public IList<Post> GetPublicPosts()
{
return repository.GetPosts().WherePublicIs(true).ToList();
}
...
}
Run Code Online (Sandbox Code Playgroud)
这是在命名空间Subnus.MVC.Service中它抛出错误
Method 'System.Linq.IQueryable`1[Subnus.MVC.Data.Model.Comment] GetCommentsByPostId(Int32)' has no supported translation to SQL.
Run Code Online (Sandbox Code Playgroud)
Bry*_*tts 25
你GetCommentsByPostId在最终的表达树中调用.组成时BlogService.GetPublicPosts,该树将转换为SQL.
在转换期间,它只是一个方法调用,仅此而已.Linq to Sql理解某些方法调用,而你的不是其中之一.因此错误.
从表面上看,这似乎应该有效.您编写可重用查询并从其他查询中编写它们.但是,你实际上说的是:"在处理数据库服务器上的每一行时,调用这个方法",这显然是做不到的.它需要一个IQueryable<T>并返回一个这一事实IQueryable<T>并不会使它变得特别.
想想这样说:您传递postId给GetCategoriesByPostId.在拥有a之前postId,不能调用该方法,并且在查询服务器上之前没有其中之一.
您可能需要Expression<>为子查询定义公共实例并使用组合中的实例.我没有想过这会是什么样子,但它肯定是可行的.
编辑:
如果你更换
let categories = GetCategoriesByPostId(p.PostId)
let comments = GetCommentsByPostId(p.PostId)
...
Categories = new LazyList<Category>(categories),
Comments = new LazyList<Comment>(comments),
Run Code Online (Sandbox Code Playgroud)
同
Categories = new LazyList<Category>(GetCategoriesByPostId(p.PostId)),
Comments = new LazyList<Comment>(GetCommentsByPostId(p.PostId)),
Run Code Online (Sandbox Code Playgroud)
查询将不再抛出异常.
这是因为let声明范围变量,它们在每行的范围内.必须在服务器上计算它们.
但是,预测允许您在任务中放置任意代码,然后在客户端上构建结果时执行.这意味着将调用这两种方法,每种方法都会发出自己的查询.
| 归档时间: |
|
| 查看次数: |
27117 次 |
| 最近记录: |