我有以下的Linq2Sql,它为我的'SELECT'语句做了不止一次往返.我不知道为什么.首先是代码,然后解释: -
from p in db.Questions
select new Models.Question
{
Title = p.Title,
TagList = (from t in p.QuestionTags
select t.Tag.Name).ToList()
}
Run Code Online (Sandbox Code Playgroud)
现在数据库是
问题<-one to many-> QuestionTags <-many to one-> Tag
所以一个问题有一个到多个标签,中间有一个链接表.这样,我可以多次重复使用标签.(如果有的话,我会对更好的架构持开放态度).
这样做会执行Linq2Sql生成的以下Sql代码
SELECT [t0].[QuestionId] AS [ID], etc.... <-- that's the good one
Run Code Online (Sandbox Code Playgroud)
.
exec sp_executesql N'SELECT [t1].[Name]
FROM [dbo].[QuestionTags] AS [t0]
INNER JOIN [dbo].[Tags] AS [t1] ON [t1].[TagId] = [t0].[TagId]
WHERE [t0].[QuestionId] = @x1',N'@x1 int',@x1=1
Run Code Online (Sandbox Code Playgroud)
第二个sql块被列为2x ..我认为这是因为第一个sql块返回两个结果,所以第二个sql块会针对第一个sql块的每个结果触发.
有什么方法可以使这个sql语句而不是1 + n,其中n =第一个查询的结果数?
我已经尝试了Eager和Lazy加载,并没有区别.
DataLoadOptions dataLoadOptions = new DataLoadOptions();
dataLoadOptions.LoadWith<Question>(x => x.QuestionTags);
dataLoadOptions.LoadWith<QuestionTag>(x => x.Tag);
db.LoadOptions = dataLoadOptions;
Run Code Online (Sandbox Code Playgroud)
ToList()肯定会阻止你.您应该对整个查询执行ToList().
我认为你可以做的另一件事就是使用"let".我认为在这种情况下,它可以创建延迟执行并包含在表达式树中,但是YMMV.
from p in db.Questions
let Tags = (from t in p.QuestionTags
select t.Tag.Name)
select new Models.Question
{
Title = p.Title,
TagList = Tags
}
Run Code Online (Sandbox Code Playgroud)
这可能是 LINQ 本身还不够的情况之一。您是否考虑过将此逻辑编写为 UDF 或 SPROC,然后简单地使用 LINQ 来调用它?LINQ-to-SQL 非常擅长调用其中任何一个(实体框架对于 UDF 不太擅长)。
然后,您可以在数据库中进行标签组合,并将其作为 varchar 返回。有一个 TSQL 技巧可以在没有游标的情况下完成此操作:
DECLARE @foo varchar(max)
SET @foo = ''
SELECT @foo = @foo + [SomeColumn] + ',' -- CSV
FROM [SomeTable]
WHERE -- some condition
Run Code Online (Sandbox Code Playgroud)
(也许删除结尾的逗号)
运行此命令后,@foo
将得到值的 CSV - 如果您返回单行,则非常有效。如果您要返回多个主行,则不太好。
归档时间: |
|
查看次数: |
810 次 |
最近记录: |