从两个表中选择*到两个单独的列表中

时间:2017-02-12 02:03:16

标签: c# entity-framework linq query-optimization

psuedocode中的基本思想

Select(a, b) => new Tuple<List<Item1>, List<Item2>>(a, b)

我试图在以下方面实现这一目标:

  • 对db
  • 的单个查询
  • 显然使用linq(查询或方法语法)

以下是涉及的两个类

public class Bundle
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public HashSet<Inventory> Inventories { get; set; }
}

public class Inventory
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public int Stock { get; set; }
}

现在我能想到的只是

 using (var context = new MyEntities())
 {
     return new Tuple<IEnumerable<Inventory>, IEnumerable<Bundle>>(context.Inventories.OrderBy(a => a.Stock).ToList()
         , context.Bundles.Include(b => b.Inventories).OrderBy(c => c.Name).ToList());
 }  

然而,这会两次击中数据库。

我知道UNION用于合并来自2个不同查询的结果集,但这两个查询必须具有相同的列数,因此我假设它在选择相同数据时最佳使用。

如何从两个不同的表中选择数据到两个单独的列表中,只有一次点击?

4 个答案:

答案 0 :(得分:2)

如果您想要两个结果集,可以通过抛出两个查询来完成。这可以在一个数据库调用中完成,没有问题,但它不会像您感兴趣的那样神奇地划分为两组对象。

事实上,当建立连接(实例化成本或延迟成本等)的成本足以保证它时,询问多个问题并获得多个结果集是非常常见的。我自己在存储过程中完成了它,在一个查询中询问页面所需的所有内容。

但是,如果性能是关键问题,缓存也很常见。并且,如果这些是下拉列表,或者列表请求的其他内容很小,并且列表不会经常更改,您甚至可以在应用程序启动时将其拉入内存并将其设置在Web服务器上,这样您就不会使数据库旅行。

我不喜欢LINQ to SQL,因为它给DBA带来了麻烦,但是你可以这样做(只有一个例子,你可以链接命令的任何方法都可以):

var connString = "{conn string here}";
var commandString = "select * from tableA; select * from tableB";
var conn = new SqlConnection(connString);
var command = new SqlCommand(commandString, conn);
try {
    conn.Open();
    var result = command.Execute();
    // work with results here
}
finally {
    conn.Dispose();
}

我没有填写所有细节,但您可以使用任意数量的命令执行此操作。再一次,如果信息没有改变,可以考虑单击并保持在内存中(通过编程缓存)或使用其他类型的缓存机制。

答案 1 :(得分:1)

如果您担心表现,我不认为减少查询量是最佳选择。事实上,如果你想要细粒度优化,LINQ也不是最合适的工具。

话虽这么说,你可以使两个不同的对象匹配相同的接口/列,为其他类型中缺少的那些填充虚拟属性。理论上,这应该转换为包含所有列的SQL union

var union = context.Inventories
    .Select(i => new { i.Id, i.Name, i.Stock, Inventories=null })
    .Concat(context.Bundles.Select(b => new { b.Id, b.Name, Stock=0, b.Inventories));

请注意,在这种情况下,Concat优先于Union,因为它不会改变行的顺序并允许重复的行。

答案 2 :(得分:0)

你要求的是不可能的。 如果您尝试获得两个不同的结果,则需要按两次DB,每个结果集一次。你可以做一个外连接,但是这会使你的结果集大于它应该的,并且从你想要一次击中DB的事实来看,你关心性能。 此外,如果性能是一个问题,我不会首先使用Linq。

答案 3 :(得分:0)

我认为你可以通过询问多个结果集来做到这一点(正如格雷戈里已经指出的那样),我不确定这将是什么“最佳”方式。你为什么不看看这篇msdn文章呢? How to: Use Stored Procedures Mapped for Multiple Result Shape

或者,对于linq-to-sql方法: LINQ to SQL: returning multiple result sets