我是一名有帮助的助手,可以为您翻译。
我目前正在处理一个使用linq2sql作为其数据库访问框架的项目,现在有很多linq查询基本上都是做以下事情:
例如假设您读取了3个表,然后将内容汇总为一个大型的高级模型,以便发送到视图。忽略域的混合,因为这不会让我太困扰,重点在于最终的where子句。
我之前没有使用过Linq2Sql,所以我的理解是:
1. 基于from、join、join、select linq生成SQL语句 2. 检索所有行 3. 将所有数据映射到一个大的模型中(在内存中) 4. 循环遍历所有模型,然后只返回适用的模型
这是我的问题核心,如果上述流程是正确的,那么这个问题在我的想法中就有意义。但是,有些人认为比我更了解这个框架,他们争论第4步已经被整合到SQL生成中,因此它不会拉回所有记录,但我不知道它是如何做到的,因为它需要所有数据来填充其中一个单独的where子句,所以我认为在第4步时,所有行都已经被读取并且已经在内存中。
我正在努力推动他们将where子句移动到Linq中,以便在数据库层面上过滤掉不需要的记录,但我想知道是否有人能够建议我上述的假设是否正确?
编辑:
已添加注释以更加关注事实,即 不是由Linq2Sql生成的对象,而是在其他地方手动编写的随机poco,在问题的上下文中突出我的主要焦点。因为问题不在于“我把where子句放在哪里有没有关系”,而是在于“当应用于从Linq2Sql查询生成的非Linq2Sql对象时,是否仍然将where子句纳入基础查询中”。以下是我希望更简洁明了的例子,以便更好地说明我的疑问所在:
我目前正在处理一个使用linq2sql作为其数据库访问框架的项目,现在有很多linq查询基本上都是做以下事情:
var result = from <some_table>
join <some_other_table>
join <another_table>
select <some_other_domain_model> // This is a non linq2SQL poco
return result.Where(<Some_Predicate>);
例如假设您读取了3个表,然后将内容汇总为一个大型的高级模型,以便发送到视图。忽略域的混合,因为这不会让我太困扰,重点在于最终的where子句。
我之前没有使用过Linq2Sql,所以我的理解是:
1. 基于from、join、join、select linq生成SQL语句 2. 检索所有行 3. 将所有数据映射到一个大的模型中(在内存中) 4. 循环遍历所有模型,然后只返回适用的模型
这是我的问题核心,如果上述流程是正确的,那么这个问题在我的想法中就有意义。但是,有些人认为比我更了解这个框架,他们争论第4步已经被整合到SQL生成中,因此它不会拉回所有记录,但我不知道它是如何做到的,因为它需要所有数据来填充其中一个单独的where子句,所以我认为在第4步时,所有行都已经被读取并且已经在内存中。
我正在努力推动他们将where子句移动到Linq中,以便在数据库层面上过滤掉不需要的记录,但我想知道是否有人能够建议我上述的假设是否正确?
编辑:
已添加注释以更加关注事实,即 不是由Linq2Sql生成的对象,而是在其他地方手动编写的随机poco,在问题的上下文中突出我的主要焦点。因为问题不在于“我把where子句放在哪里有没有关系”,而是在于“当应用于从Linq2Sql查询生成的非Linq2Sql对象时,是否仍然将where子句纳入基础查询中”。以下是我希望更简洁明了的例子,以便更好地说明我的疑问所在:
/*
I am only going to put auto properties into the linq2sql entities,
although in the real world they would be a mix of private backing
fields with public properties doing the notiftying.
*/
[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.some_table_1")]
public class SomeLinq2SqlTable1
{
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="some_table_1_id", AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true)]
public int Id {get;set;}
}
[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.some_table_2")]
public class SomeLinq2SqlTable2
{
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="some_table_2_id", AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL", IsPrimaryKey=true, IsDbGenerated=true)]
public int Id {get;set;}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="some_table_2_name", AutoSync=AutoSync.OnInsert, DbType="Varchar NOT NULL", IsPrimaryKey=false)]
public string Name {get;set;}
}
[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.some_table_3")]
public class SomeLinq2SqlTable3
{
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="some_table_3_id", AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL", IsPrimaryKey=true, IsDbGenerated=true)]
public int Id {get;set;}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="some_table_3_other", AutoSync=AutoSync.OnInsert, DbType="Varchar NOT NULL", IsPrimaryKey=false)]
public string Other {get;set;}
}
/*
This is some hand rolled Poco, has NOTHING to do with Linq2Sql, think of it as
a view model of sorts.
*/
public class SomeViewModel
{
public int Id {get;set;}
public string Name {get;set;}
public string Other {get;set;}
}
/*
Here is psudo query to join all tables, then populate the
viewmodel item from the query and finally do a where clause
on the viewmodel objects.
*/
var result = from // Linq2SqlTable1 as t1
join // Linq2SqlTable2.id on Linq2SqlTable1.id as t2
join // Linq2SqlTable3.id on Linq2SqlTable1.id as t3
select new ViewModel { Id = t1.Id, Name = t2.Name, Other = t3.Other }
return result.Where(viewModel => viewModel.Name.Contains("some-guff"));
考虑上面的例子,最终的Where语句是否会被纳入基础查询中?还是viewModel上的where会导致检索并在内存中评估?
对于这个问题的描述可能有些啰嗦,但是关于它的文档非常少,而且这是一个非常具体的问题。
Select new RandomModel { id = table1.Id, name = table2.Name, other = table3.data}
然后应用一个 where 子句,比如randomModel => randomModel.Name.Contains("foo");
那么它只能通过拉回所有100行数据,组成列表,然后在内存中逐一评估每个对象,或者拉回每个单独的行来创建对象,然后在内存中执行 where 子句。 - Grofitwhere
和单独应用Where
之间绝对没有任何区别。它可以将where
组成SQL。LINQ语法只是对基础的.Where、.Join等的方便封装。所有的LINQ查询都是由多个单独的调用组成的。系统甚至无法检测到Where
是后来添加的,还是在原始LINQ中添加的。简而言之:它可以把where
放进TSQL。 - Marc Gravelldb.Log = Console.Out;
。这是好的。它实际上并不会为每一行创建一个SomeViewModel
- 它只是跟踪视图模型Name
与t2.Name
相同,并使用它。如果你看看join
和let
等在幕后的工作方式,就会明白这个问题变得微不足道的原因:实际上,有很多隐藏的更广泛的类型被生成来表示组合的连接模型(在规范中称为“不透明标识符”之类的东西)。解析器已经知道如何做到这一点。 - Marc Gravell.Log
属性,你可以附加任何文本输出(例如Console.Out
或者一个StringWriter
,如果我没记错的话)- 允许你监视它。另外,像mini-profiler这样的工具可以用来记录所有的ADO.NET流量(对于开发人员而言)。如果我(作为开发人员)在我的网站上加载一个页面,我可以看到所有发生的SQL操作。还有很多其他的东西。 - Marc Gravell