Linq to sql LINQ to SQL:调用First()或Take()时生成一个查询

Linq to sql LINQ to SQL:调用First()或Take()时生成一个查询,linq-to-sql,one-to-many,Linq To Sql,One To Many,我有一个包含以下表格的数据库: create table Categories ( Id int primary key, Name nvarchar(256) not null) create table Products ( Id int primary key, Name nvarchar(256) not null, CategoryId int not null, foreign key (CategoryId) references Categories (

我有一个包含以下表格的数据库:

create table Categories (
  Id int primary key,
  Name nvarchar(256) not null)

create table Products (
  Id int primary key,
  Name nvarchar(256) not null,
  CategoryId int not null,
  foreign key (CategoryId) references Categories (Id))
使用
DataLoadOptions
,我可以编写以下内容:

DataLoadOptions dlo = new DataLoadOptions();
dlo.LoadWith<Category>(c => c.Products);
访问
类别
实例的
产品
属性将导致另一个查询执行

我发现了一些方法来解决这个问题

// For First():
var category = db.Categories.Single(c => c == db.Categories.First());

// For FirstOrDefault():
var category = db.Categories.SingleOrDefault(c => c == db.Categories.First());

// For Take(10):
var categories = db.Categories.Where(c => db.Categories.Take(10).Contains(c));
以上所有LINQ语句都将在一次查询中返回
类别
条目子集的所有类别和产品信息


有人知道有没有更好或更有效的方法来实现这一点吗?谢谢。

您应该在此处阅读有关跳过、获取和加载相关收藏的内容:

坏消息是这个解决方案对你不起作用。CompiledQuery对LoadOptions过敏-您将得到运行时错误


访问产品的产品属性 类别实例将导致 另一个查询执行

挑剔。这不完全是真的。当您对First的调用返回时,产品将被提取。LoadsWith的契约是获取数据。问题在于,它不能保证使用最高效的查询进行抓取(在本例中是一个带有ROWNUMBER的查询)

下面是一个方法实现,它确认:

        DataClasses1DataContext myDC = new DataClasses1DataContext();
        var myOptions = new System.Data.Linq.DataLoadOptions();
        myOptions.LoadWith<Customer>(c => c.Orders);
        myDC.LoadOptions = myOptions;

        myDC.Log = Console.Out;


        myDC.Customers.Take(10).ToList();
DataClasses1DataContext myDC=newdataclasses1datacontext();
var myOptions=new System.Data.Linq.DataLoadOptions();
LoadWith(c=>c.Orders);
myDC.LoadOptions=myOptions;
myDC.Log=Console.Out;
myDC.Customers.Take(10.ToList();
为客户发出1个查询,然后是10个查询,每个客户的订单发出1个查询。即使未访问任何客户实例的订单属性,也会发生这10个查询



KWatkins的这篇文章演示了如何在CompiledQuery中使用LoadOptions。这将打开CompiledQuery,作为锁定跳过(x)的一种方式,即使x可能为0。

您应该在此处阅读有关跳过、获取和加载相关集合的内容:

坏消息是这个解决方案对你不起作用。CompiledQuery对LoadOptions过敏-您将得到运行时错误


访问产品的产品属性 类别实例将导致 另一个查询执行

挑剔。这不完全是真的。当您对First的调用返回时,产品将被提取。LoadsWith的契约是获取数据。问题在于,它不能保证使用最高效的查询进行抓取(在本例中是一个带有ROWNUMBER的查询)

下面是一个方法实现,它确认:

        DataClasses1DataContext myDC = new DataClasses1DataContext();
        var myOptions = new System.Data.Linq.DataLoadOptions();
        myOptions.LoadWith<Customer>(c => c.Orders);
        myDC.LoadOptions = myOptions;

        myDC.Log = Console.Out;


        myDC.Customers.Take(10).ToList();
DataClasses1DataContext myDC=newdataclasses1datacontext();
var myOptions=new System.Data.Linq.DataLoadOptions();
LoadWith(c=>c.Orders);
myDC.LoadOptions=myOptions;
myDC.Log=Console.Out;
myDC.Customers.Take(10.ToList();
为客户发出1个查询,然后是10个查询,每个客户的订单发出1个查询。即使未访问任何客户实例的订单属性,也会发生这10个查询



KWatkins的这篇文章演示了如何在CompiledQuery中使用LoadOptions。这将打开CompiledQuery,作为锁定跳过(x)的一种方式,即使x可能为0。

@David。谢谢你的额外阅读,尽管它对我不起作用。我仍然不明白你为什么说我的陈述是假的。它不会导致多个查询执行吗?会导致多个查询结果,但它是立即执行的,不会等到您访问Products属性时才执行。@David。我在测试中没有看到这一点。有关于这方面的文档吗?这个事实:“加载选项可能导致迭代查询”没有文档记录。我看到迭代查询产生的情况比问题中提到的更多。因此,只有在您愿意检查生成的输出(通过DataContext.Log或Sql profiler)时才使用LoadsWith。我不会将LoadsWith用于动态查询场景。@David。在我对上述示例的测试中,DataContext.Log和SQL Server Profiler都显示了多个查询执行,但仅在访问Products属性时显示。您能给我一个可复制的场景,在访问属性之前获取结果吗?谢谢,大卫。谢谢你的额外阅读,尽管它对我不起作用。我仍然不明白你为什么说我的陈述是假的。它不会导致多个查询执行吗?会导致多个查询结果,但它是立即执行的,不会等到您访问Products属性时才执行。@David。我在测试中没有看到这一点。有关于这方面的文档吗?这个事实:“加载选项可能导致迭代查询”没有文档记录。我看到迭代查询产生的情况比问题中提到的更多。因此,只有在您愿意检查生成的输出(通过DataContext.Log或Sql profiler)时才使用LoadsWith。我不会将LoadsWith用于动态查询场景。@David。在我对上述示例的测试中,DataContext.Log和SQL Server Profiler都显示了多个查询执行,但仅在访问Products属性时显示。您能给我一个可复制的场景,在访问属性之前获取结果吗?谢谢。我已经加了一笔赏金,因为我的信息丰富的非答案对我来说不够有用。@David。谢谢我很感激。我已经加了一笔赏金,因为我的信息丰富的非答案对我来说不够有用。@David。谢谢我很感激。