Linq to sql 如何加载多对多LINQ查询?
我有以下(相当标准的)表结构:Linq to sql 如何加载多对多LINQ查询?,linq-to-sql,Linq To Sql,我有以下(相当标准的)表结构: Post <-> PostTag <-> Tag 换句话说,第一篇文章有两个标签,第二篇有一个,第三篇没有 我想在一个查询中加载所有帖子及其标签,但无法找到正确的运算符组合。我已经能够加载只有标签的帖子,或者在有多个标签的情况下加载重复的帖子 鉴于上述数据库,我希望在Post对象的集合属性中接收三篇文章及其标记(如果有)。有可能吗 谢谢我在另一篇帖子中回答了这个问题:。在您的情况下,可能是这样的: DataLoadOptions opti
Post <-> PostTag <-> Tag
换句话说,第一篇文章有两个标签,第二篇有一个,第三篇没有
我想在一个查询中加载所有帖子及其标签,但无法找到正确的运算符组合。我已经能够加载只有标签的帖子,或者在有多个标签的情况下加载重复的帖子
鉴于上述数据库,我希望在Post对象的集合属性中接收三篇文章及其标记(如果有)。有可能吗
谢谢我在另一篇帖子中回答了这个问题:。在您的情况下,可能是这样的:
DataLoadOptions options = new DataLoadOptions();
options.LoadWith<Post>(p => p.PostTag);
options.LoadWith<PostTag>(pt => pt.Tag);
DataLoadOptions=newdataloadoptions();
options.LoadWith(p=>p.PostTag);
options.LoadWith(pt=>pt.Tag);
尽管要小心-必须在将任何查询发送到数据库之前设置DataLoadOptions-否则,将引发异常(不知道为什么在Linq2Sql中会出现这种情况-可能会在以后的版本中得到修复)。很抱歉,不,每个post的每个标记都将执行一个额外的查询 使用此代码进行测试:
var options = new DataLoadOptions();
options.LoadWith<Post>(p => p.PostTags);
options.LoadWith<PostTag>(pt => pt.Tag);
using (var db = new BlogDataContext())
{
db.LoadOptions = options;
return (from p in db.Posts
where p.Status != PostStatus.Closed
orderby p.PublishDateGmt descending
select p);
}
var options=new DataLoadOptions();
options.LoadWith(p=>p.PostTags);
options.LoadWith(pt=>pt.Tag);
使用(var db=new BlogDataContext())
{
db.LoadOptions=选项;
返回(从数据库中的p返回)
其中p.Status!=PostStatus.Closed
orderby p.PublishDateGmt降序
选择p);
}
在示例数据库中,它将执行4个在生产中不可接受的查询。有人能提出另一个解决方案吗
谢谢,这有点奇怪,因为
DataLoadOptions o = new DataLoadOptions ( );
o.LoadWith<Listing> ( l => l.ListingStaffs );
o.LoadWith<ListingStaff> ( ls => ls.MerchantStaff );
ctx.LoadOptions = o;
IQueryable<Listing> listings = (from a in ctx.Listings
where a.IsActive == false
select a);
List<Listing> list = listings.ToList ( );
(我缩短了名称,并在选择栏上添加了*)
所以它似乎做了选择ok。对不起。您给出的解决方案是有效的,但我发现在使用Take(N)分页时它会中断。我使用的完整方法如下:
public IList<Post> GetPosts(int page, int records)
{
var options = new DataLoadOptions();
options.LoadWith<Post>(p => p.PostTags);
options.LoadWith<PostTag>(pt => pt.Tag);
using (var db = new BlogDataContext())
{
db.LoadOptions = options;
return (from p in db.Posts
where p.Status != PostStatus.Closed
orderby p.PublishDateGmt descending
select p)
.Skip(page * records)
//.Take(records)
.ToList();
}
}
SELECT p.PostID, p.Title, pt.PostID, pt.TagID, t.TagID, t.Name FROM Posts p
JOIN PostsTags pt ON p.PostID = pt.PostID
JOIN Tags t ON pt.TagID = t.TagID
WHERE p.PostID IN (SELECT TOP 10 PostID FROM Posts)
public IList GetPosts(int页,int记录)
{
var options=new DataLoadOptions();
options.LoadWith(p=>p.PostTags);
options.LoadWith(pt=>pt.Tag);
使用(var db=new BlogDataContext())
{
db.LoadOptions=选项;
返回(从数据库中的p返回)
其中p.Status!=PostStatus.Closed
orderby p.PublishDateGmt降序
选择p)
.跳过(第*页记录)
//.Take(记录)
.ToList();
}
}
使用Take()方法,它会生成一个与您发布的内容类似的查询,但如果我再次添加Take(),它会生成1+nxm查询
因此,我想我现在的问题是:是否有替代Take()方法的方法来分页记录?
谢谢耶!成功了
如果有人有同样的问题,我会这样做:
public IList<Post> GetPosts(int page, int record)
{
var options = new DataLoadOptions();
options.LoadWith<Post>(p => p.PostTags);
options.LoadWith<PostTag>(pt => pt.Tag);
using (var db = new DatabaseDataContext(m_connectionString))
{
var publishDateGmt = (from p in db.Posts
where p.Status != PostStatus.Hidden
orderby p.PublishDateGmt descending
select p.PublishDateGmt)
.Skip(page * record)
.Take(record)
.ToList()
.Last();
db.LoadOptions = options;
return (from p in db.Posts
where p.Status != PostStatus.Closed
&& p.PublishDateGmt >= publishDateGmt
orderby p.PublishDateGmt descending
select p)
.Skip(page * record)
.ToList();
}
}
public IList GetPosts(int页,int记录)
{
var options=new DataLoadOptions();
options.LoadWith(p=>p.PostTags);
options.LoadWith(pt=>pt.Tag);
使用(var db=newdatabasedatacontext(m_connectionString))
{
var publishDateGmt=(从数据库中的p开始)
其中p.Status!=PostStatus.Hidden
orderby p.PublishDateGmt降序
选择p.PublishDateGmt)
.跳过(第*页记录)
.记录
托利斯先生()
.Last();
db.LoadOptions=选项;
返回(从数据库中的p返回)
其中p.Status!=PostStatus.Closed
&&p.PublishDateGmt>=PublishDateGmt
orderby p.PublishDateGmt降序
选择p)
.跳过(第*页记录)
.ToList();
}
}
这只执行两个查询并加载每个帖子的所有标记
我们的想法是在我们需要的最后一篇文章中获取一些值来限制查询(在本例中,PublishDateGmt列就足够了),然后使用该值而不是Take()来限制第二个查询
感谢您的帮助sirrocco。我知道这是一篇老文章,但我发现了一种方法,可以在只执行一个查询时使用Take()。诀窍是在嵌套查询中执行Take()
var q = from p in db.Posts
where db.Posts.Take(10).Contains(p)
select p;
在上面的查询中使用DataLoadOptions将在一个查询中为您提供前十篇文章,包括它们的关联标记。由此产生的SQL将是以下内容的一个不那么简洁的版本:
public IList<Post> GetPosts(int page, int records)
{
var options = new DataLoadOptions();
options.LoadWith<Post>(p => p.PostTags);
options.LoadWith<PostTag>(pt => pt.Tag);
using (var db = new BlogDataContext())
{
db.LoadOptions = options;
return (from p in db.Posts
where p.Status != PostStatus.Closed
orderby p.PublishDateGmt descending
select p)
.Skip(page * records)
//.Take(records)
.ToList();
}
}
SELECT p.PostID, p.Title, pt.PostID, pt.TagID, t.TagID, t.Name FROM Posts p
JOIN PostsTags pt ON p.PostID = pt.PostID
JOIN Tags t ON pt.TagID = t.TagID
WHERE p.PostID IN (SELECT TOP 10 PostID FROM Posts)