使用linq选择特定的列:传输的内容



我引用这个例子:返回选定的指定列

引用:如果BlobDetails不是LINQ实体,那么您可以直接这样做:

var qry = from b in dc.Blobs
          orderby b.RowVersion descending
          select new BlobDetails {
              Id = b.Id, Size = b.Size,
              Signature = b.Signature, RowVersion = b.RowVersion};
return qry.ToList();

我看到他们正在通过orm工具LINQ TO SQL选择查询中的特定列。orm工具的批评者说,如果我没记错的话,orm工具从表中选择并返回整个对象,并且限制了仅选择特定列的选项,就像通过经典sql编程可以做到的那样。当然,当我看到这个示例时,我对此有所怀疑,但是,我仍然不断地问自己这个问题:数据库是只返回选定的列,还是返回整个对象,将列过滤留给orm工具?

在这个例子中,他们也有一个叫做Blobdetails的类:

public class BlobDetails   
{  
    public int Id { get; set; }  
    public string Signature { get; set; }  
    public int Size { get; set; }  
    public System.Data.Linq.Binary RowVersion { get; set; }     
}

我需要创建我自己的类,每次我只希望通过LINQ从表中选择几列吗?

您不需要创建新的类来从表中选择一些列。您可以使用匿名类型。

var qry = from b in dc.Blobs
          orderby b.RowVersion descending
          select new { b.Id, b.Size, b.Signature, b.RowVersion};
return qry.ToList();

只传输选定的列。使用普通SQL和使用LINQ to SQL之间没有区别。当执行LINQ查询时,它被转换为普通SQL并执行。然后将结果映射到您的对象。

您可以使用SQL Server Profiler查看在服务器上生成和执行的查询。您还可以使用LINQPad查看将从您的查询生成哪些SQL。在您的情况下,查询将是相同的,您使用BlobDetails或匿名对象:

SELECT [t0].[Id], [t0].[Size], [t0].[Signature], [t0].[RowVersion]
FROM [Blobs] AS [t0]
ORDER BY [t0].[RowVersion] DESC

当您做投影时,LINQ确实只选择那些列,并且没有任何东西可以阻止您实现它。在你的示例代码

select new BlobDetails 
{
  Id = b.Id, 
  Size = b.Size,
  Signature = b.Signature, 
  RowVersion = b.RowVersion
};

只有b.id, b.size, b.signature, &b.选择行版本。你可以用sql分析器或调试器来验证这一点,我似乎记得还有一个函数,你可以在数据上下文中调用,以获得运行的最后一个查询。

我认为你第一个问题的答案已经在你提到的POST中了。然而…

如果你的BlobDetails不是LINQ实体,你可以简单地在你的select语句中使用它来定义(收缩)你的投影属性。例如:

var qry = from b in dc.Blobs
          select new BlobDetails { Id = b.Id, Size = b.Size }

将编译成类似SELECT Id, Size FROM Blob ....

的SQL查询

但是如果BlobDetails是LINQ实体,您将需要使用AsEnumerable() hack,否则您将获得NotSupportedException: Explicit construction of entity type in query is not allowed

var qry = from b in dc.Blobs.AsEnumerable()
          select new BlobDetails { Id = b.Id, Size = b.Size }

编辑

正如@Chris Pitman在他的评论中所说,这种AsEnumerable()方法可能会造成严重的瓶颈,因为在应用投影之前,整个表将被加载到内存中。所以不推荐!

对于你的第二个问题:

您需要为您希望在方法作用域之外轻松使用的对象创建自定义类。匿名对象的属性只在作用域中可见,并且匿名对象只能被强制转换为object类型。

所以如果你想从方法中返回匿名对象,返回类型必须是objectdynamic的可枚举值,正如@xeondev在他的评论中所说的。

不需要创建自己的类,可以返回匿名类型。你可以这样写

var qry = from b in dc.Blobs
          orderby b.RowVersion descending
          select new {
              Id = b.Id, Size = b.Size,
              Signature = b.Signature, RowVersion = b.RowVersion};
return qry.ToList();

尽管方法的签名应该看起来像这样

public  IEnumerable<object> GetItems()

public dynamic GetItems()

因此,如果你打算在外部作用域中使用linq查询的结果,就像你的例子建议的那样,强烈建议你创建自己的类。

相关内容

  • 没有找到相关文章

最新更新