如何在不使用基本查询的情况下在一个操作中解析多个linq查询?

时间:2009-05-06 15:12:44

标签: c# .net linq linq-to-sql

我在一个方法中有14个LINQ查询要解决。它们都没有基本查询,我可以将它们作为子查询挂起,然后将结果存储为匿名类型实例的属性。

我怎样才能确保在同一个操作中调用它们,而不是对数据库进行14次单独调用?

更新

我最终使用了一个狡猾的黑客来完成这个伎俩。我知道用户表中总会至少有一个用户,所以我最终使用了:

var data = (from tmp in DataContext.Users
            select new {
                Property1 = (from...),
                Property2 = (from...),
                PropertyN = (from...),
            }).First();

更新2

其中一个答案暗示这样做可能会产生MARS(多个活动结果集)错误。这些错误是什么(我从未见过),它们为什么会出现,这一问题的整个前提是否有任何错误?即,我的断言中,要求数据库一次性返回所有内容,是否会比执行十四个完全独立的LINQ查询更快/更有效?

更新3

我认为我的方法是多余的,从务实的角度来看,应该通过存储过程或某种延迟/混合方法来区别对待。

7 个答案:

答案 0 :(得分:3)

您仍在通过每个子查询对数据库进行14次单独调用,只需在调用数据对象时在单个实例上执行此操作。

编辑:

如果连接有多个打开的数据读取器,则会发生MARS错误。默认情况下,SQl 2005会关闭此功能。在您的查询中,当所有SQL传递到一个命中时仍然返回14个数据站。除非您告诉连接允许多个活动结果集(MARS),否则datareader将独占地连接该连接。

要解决此问题,您需要将每个子查询预加载到列表中并从该列表中运行子查询,或者您需要设置连接字符串的MutlipleActiveResultSet属性= true。

<add name="Name" connectionString="Data Source=<server>;Initial Catalog=<database>;Integrated Security=True;MultipleActiveResultSets=true" providerName="System.Data.SqlClient"/>

答案 1 :(得分:0)

我不完全确定您的查询,但您可以将查询逻辑封装在存储过程中,将其拖放到LINQ to SQL数据上下文设计器中以供使用。

如果你需要独立的结果并且你真的不希望往返数据库服务器,我认为你应该回到SqlDataReader并通过调用一个检索整个过程的过程来使用NextResult数据

答案 2 :(得分:0)

您可以为每个查询获取SQL代码,然后在一个批处理中将其发送到数据库,最后遍历14个结果集。

答案 3 :(得分:0)

内森,你说这些查询不一定是相互依赖的,但都是相关的。我们需要知道的是,它们实际上是14个不同的结果集,还是可以组合在一个结果集中。如果是后者,为什么不能为此目的创建视图或存储过程?在某些情况下,您需要使用判断来辨别何时使用其他路线以获得更好的性能并完成工作。混合方法一点都不差。

如果您需要14个不同的结果集,则可以使用多个活动结果集(MARS),方法是在连接字符串中启用它。这样他们就可以在一次往返中完成。

答案 4 :(得分:0)

如果你重写你的'狡猾的黑客',它应该模拟运行查询:

var data = from a in (from x in ... select x)
           from b in (from x in ... select y)
           from c in (from x in ... select z)
           select new { A = a, B = b, C = c };
var result = data.First();

但是,它会对所有项目进行完全连接,这可能不是您想要的。如果查询都返回相同数量的列,则使用IQueryable.Concat可能会起作用:

var data = (from x in ... select new { Part = 1, Val = x })
    .AsQueryable() // may not be needed in your context
    .Concat(
        (from y in ... select new { Part = 2, Val = y })
            .AsQueryable()
            .Concat(
                (from z in ... select new { Part = 3, Val = z }).AsQueryable()
            )
    );
foreach (result in data)
{
    switch (result.Part)
    {
        // process each query's resultset
    }
}

仍然狡猾(并且未经测试),但应该只打一次DB。

答案 5 :(得分:0)

我不确定在Users表中执行查询确实对你有所帮助。

在编写LINQ查询之前,请尝试考虑如何使用基本SQL实现目标。

我不确定你要做的是什么,因为你没有提供太多的代码,但是,如果你要在存储过程中这样做,那会是什么样的,它会返回什么?

我问这个是因为你需要的数据结构可能不适合单个查询。

如果确实如此,那么您只需要重新考虑整个LINQ方法。

也许您可以提供有关您实际尝试检索哪些数据以及如何检索的更多信息?

欢呼声

答案 6 :(得分:0)

不确定这是否有帮助,但想知道为什么不使用let关键字来增强查询。

'let'允许您运行子查询并将结果存储在临时变量中,然后您可以在主查询中进一步使用