EF Linq to Entities在实体集上调用ToList()会生成包含多个左外连接的SQL命令

我的实体“Progetto”映射名为VW_AMY_PRG_WCS_Lookup的视图

在此处输入图像描述

Progetto有五个导航属性:ClienteDiFatturazione,ClienteDiLavorazione,PercentualeSuccesso,Agente具有多重性0..1和DocumentiWcs具有mupltiplicity *

当我在LINQPad中运行这个简单的语句时

var prj = Progetti.AsQueryable(); prj.ToList(); 

生成的sql是

 SELECT [Extent1].[IdProgetto] AS [IdProgetto], [Extent1].[IdSerie_Progetto] AS [IdSerie_Progetto], [Extent1].[Importo] AS [Importo], [Extent1].[Data_Prevista_Chiusura] AS [Data_Prevista_Chiusura], [Extent1].[IdStato] AS [IdStato], [Extent1].[Oggetto] AS [Oggetto], [Extent1].[IdMezzo_Pervenuto] AS [IdMezzo_Pervenuto], [Extent1].[IdAgente] AS [IdAgente], [Extent1].[Fido_Residuo] AS [Fido_Residuo], [Extent2].[IdAnagrafica_Fatturazione] AS [IdAnagrafica_Fatturazione], [Extent3].[IdAnagrafica_Lavorazione] AS [IdAnagrafica_Lavorazione], [Extent4].[IdPercentuale_Successo] AS [IdPercentuale_Successo] FROM (SELECT [VW_AMY_PRG_WCS_Lookup].[IdProgetto] AS [IdProgetto], [VW_AMY_PRG_WCS_Lookup].[IdSerie_Progetto] AS [IdSerie_Progetto], [VW_AMY_PRG_WCS_Lookup].[Importo] AS [Importo], [VW_AMY_PRG_WCS_Lookup].[IdPercentuale_Successo] AS [IdPercentuale_Successo], [VW_AMY_PRG_WCS_Lookup].[Data_Prevista_Chiusura] AS [Data_Prevista_Chiusura], [VW_AMY_PRG_WCS_Lookup].[IdAnagrafica_Lavorazione] AS [IdAnagrafica_Lavorazione], [VW_AMY_PRG_WCS_Lookup].[IdAnagrafica_Fatturazione] AS [IdAnagrafica_Fatturazione], [VW_AMY_PRG_WCS_Lookup].[IdMezzo_Pervenuto] AS [IdMezzo_Pervenuto], [VW_AMY_PRG_WCS_Lookup].[IdStato] AS [IdStato], [VW_AMY_PRG_WCS_Lookup].[Oggetto] AS [Oggetto], [VW_AMY_PRG_WCS_Lookup].[IdAgente] AS [IdAgente], [VW_AMY_PRG_WCS_Lookup].[Fido_Residuo] AS [Fido_Residuo] FROM [dbo].[VW_AMY_PRG_WCS_Lookup] AS [VW_AMY_PRG_WCS_Lookup]) AS [Extent1] LEFT OUTER JOIN (SELECT [VW_AMY_PRG_WCS_Lookup].[IdProgetto] AS [IdProgetto], [VW_AMY_PRG_WCS_Lookup].[IdSerie_Progetto] AS [IdSerie_Progetto], [VW_AMY_PRG_WCS_Lookup].[Importo] AS [Importo], [VW_AMY_PRG_WCS_Lookup].[IdPercentuale_Successo] AS [IdPercentuale_Successo], [VW_AMY_PRG_WCS_Lookup].[Data_Prevista_Chiusura] AS [Data_Prevista_Chiusura], [VW_AMY_PRG_WCS_Lookup].[IdAnagrafica_Lavorazione] AS [IdAnagrafica_Lavorazione], [VW_AMY_PRG_WCS_Lookup].[IdAnagrafica_Fatturazione] AS [IdAnagrafica_Fatturazione], [VW_AMY_PRG_WCS_Lookup].[IdMezzo_Pervenuto] AS [IdMezzo_Pervenuto], [VW_AMY_PRG_WCS_Lookup].[IdStato] AS [IdStato], [VW_AMY_PRG_WCS_Lookup].[Oggetto] AS [Oggetto], [VW_AMY_PRG_WCS_Lookup].[IdAgente] AS [IdAgente], [VW_AMY_PRG_WCS_Lookup].[Fido_Residuo] AS [Fido_Residuo] FROM [dbo].[VW_AMY_PRG_WCS_Lookup] AS [VW_AMY_PRG_WCS_Lookup]) AS [Extent2] ON ([Extent2].[IdAnagrafica_Fatturazione] IS NOT NULL) AND ([Extent1].[IdProgetto] = [Extent2].[IdProgetto]) AND ([Extent1].[IdSerie_Progetto] = [Extent2].[IdSerie_Progetto]) LEFT OUTER JOIN (SELECT [VW_AMY_PRG_WCS_Lookup].[IdProgetto] AS [IdProgetto], [VW_AMY_PRG_WCS_Lookup].[IdSerie_Progetto] AS [IdSerie_Progetto], [VW_AMY_PRG_WCS_Lookup].[Importo] AS [Importo], [VW_AMY_PRG_WCS_Lookup].[IdPercentuale_Successo] AS [IdPercentuale_Successo], [VW_AMY_PRG_WCS_Lookup].[Data_Prevista_Chiusura] AS [Data_Prevista_Chiusura], [VW_AMY_PRG_WCS_Lookup].[IdAnagrafica_Lavorazione] AS [IdAnagrafica_Lavorazione], [VW_AMY_PRG_WCS_Lookup].[IdAnagrafica_Fatturazione] AS [IdAnagrafica_Fatturazione], [VW_AMY_PRG_WCS_Lookup].[IdMezzo_Pervenuto] AS [IdMezzo_Pervenuto], [VW_AMY_PRG_WCS_Lookup].[IdStato] AS [IdStato], [VW_AMY_PRG_WCS_Lookup].[Oggetto] AS [Oggetto], [VW_AMY_PRG_WCS_Lookup].[IdAgente] AS [IdAgente], [VW_AMY_PRG_WCS_Lookup].[Fido_Residuo] AS [Fido_Residuo] FROM [dbo].[VW_AMY_PRG_WCS_Lookup] AS [VW_AMY_PRG_WCS_Lookup]) AS [Extent3] ON ([Extent3].[IdAnagrafica_Lavorazione] IS NOT NULL) AND ([Extent1].[IdProgetto] = [Extent3].[IdProgetto]) AND ([Extent1].[IdSerie_Progetto] = [Extent3].[IdSerie_Progetto]) LEFT OUTER JOIN (SELECT [VW_AMY_PRG_WCS_Lookup].[IdProgetto] AS [IdProgetto], [VW_AMY_PRG_WCS_Lookup].[IdSerie_Progetto] AS [IdSerie_Progetto], [VW_AMY_PRG_WCS_Lookup].[Importo] AS [Importo], [VW_AMY_PRG_WCS_Lookup].[IdPercentuale_Successo] AS [IdPercentuale_Successo], [VW_AMY_PRG_WCS_Lookup].[Data_Prevista_Chiusura] AS [Data_Prevista_Chiusura], [VW_AMY_PRG_WCS_Lookup].[IdAnagrafica_Lavorazione] AS [IdAnagrafica_Lavorazione], [VW_AMY_PRG_WCS_Lookup].[IdAnagrafica_Fatturazione] AS [IdAnagrafica_Fatturazione], [VW_AMY_PRG_WCS_Lookup].[IdMezzo_Pervenuto] AS [IdMezzo_Pervenuto], [VW_AMY_PRG_WCS_Lookup].[IdStato] AS [IdStato], [VW_AMY_PRG_WCS_Lookup].[Oggetto] AS [Oggetto], [VW_AMY_PRG_WCS_Lookup].[IdAgente] AS [IdAgente], [VW_AMY_PRG_WCS_Lookup].[Fido_Residuo] AS [Fido_Residuo] FROM [dbo].[VW_AMY_PRG_WCS_Lookup] AS [VW_AMY_PRG_WCS_Lookup]) AS [Extent4] ON ([Extent4].[IdPercentuale_Successo] IS NOT NULL) AND ([Extent1].[IdProgetto] = [Extent4].[IdProgetto]) AND ([Extent1].[IdSerie_Progetto] = [Extent4].[IdSerie_Progetto]) 

我想知道为什么生成的SQL查询涉及这么多左外连接; 我希望在VW_AMY_PRG_WCS_Lookup上进行简单的选择。 这种行为的目的是什么? 作为映射到View多个联接的实体会对查询性能产生重大影响。 任何解决方法?

更新作为VW_AMY_PRG_WCS_Lookup视图我必须手动添加所有关联和导航属性(在数据库级别没有定义fk,因此在从数据库创建模型时不会生成关联)

IdAnagrafica_Fatturazione指的是ClienteDIfatturazione,IdAnagrafica_Lavorazione指的是ClienteDiLavorazione,IdPercentuale_Successo指的是PercentualeSuccesso和IdAgente指的是Agente,我只是在模型中重命名了这个字段,所以他们的名字与视图中的字段有点不同。

这是Progetto类的代码

 //------------------------------------------------------------------------------ //  // This code was generated from a template. // // Manual changes to this file may cause unexpected behavior in your application. // Manual changes to this file will be overwritten if the code is regenerated. //  //------------------------------------------------------------------------------ namespace EntityModel { using System; using System.Collections.Generic; public partial class Progetto { [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] public Progetto() { this.DocumentiWcs = new HashSet(); } public int Codice { get; set; } public int Serie { get; set; } public Nullable Importo { get; set; } public Nullable DataPrevistaChiusura { get; set; } public Nullable IdStato { get; set; } public string Oggetto { get; set; } public Nullable IdMezzoPervenuto { get; set; } public Nullable IdAgente { get; set; } public Nullable FidoResiduo { get; set; } public virtual Cliente ClienteDiFatturazione { get; set; } public virtual Cliente ClienteDiLavorazione { get; set; } public virtual PercentualeSuccesso PercentualeSuccesso { get; set; } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] public virtual ICollection DocumentiWcs { get; set; } public virtual Agente Agente { get; set; } } } 

这里是视图VW_AMY_PRG_WCS_Lookup的DefiningQuery

   SELECT [VW_AMY_PRG_WCS_Lookup].[IdProgetto] AS [IdProgetto], [VW_AMY_PRG_WCS_Lookup].[IdSerie_Progetto] AS [IdSerie_Progetto], [VW_AMY_PRG_WCS_Lookup].[Importo] AS [Importo], [VW_AMY_PRG_WCS_Lookup].[IdPercentuale_Successo] AS [IdPercentuale_Successo], [VW_AMY_PRG_WCS_Lookup].[Data_Prevista_Chiusura] AS [Data_Prevista_Chiusura], [VW_AMY_PRG_WCS_Lookup].[IdAnagrafica_Lavorazione] AS [IdAnagrafica_Lavorazione], [VW_AMY_PRG_WCS_Lookup].[IdAnagrafica_Fatturazione] AS [IdAnagrafica_Fatturazione], [VW_AMY_PRG_WCS_Lookup].[IdMezzo_Pervenuto] AS [IdMezzo_Pervenuto], [VW_AMY_PRG_WCS_Lookup].[IdStato] AS [IdStato], [VW_AMY_PRG_WCS_Lookup].[Oggetto] AS [Oggetto], [VW_AMY_PRG_WCS_Lookup].[IdAgente] AS [IdAgente], [VW_AMY_PRG_WCS_Lookup].[Fido_Residuo] AS [Fido_Residuo] FROM [dbo].[VW_AMY_PRG_WCS_Lookup] AS [VW_AMY_PRG_WCS_Lookup]  

原因是您不在查询中使用Select 。 因此选择原始类。

您应该只选择您真正计划使用的属性。

以下是经过测试的解决方案,它只会加入您请求中使用的表格。 唉,我的意大利语(?)有点生疏,如果我不使用正确的标识符,请原谅我。

 var result = myDbContext.Progretti .Select(progret => new // from every Progret make one new object { // containing only the properties you plan to use Id = progret.Id, Name = progret.Name ProgrettiDiFacturazione = new // you can even use properties from other tables { // again: only properties you plan to use Name = progret.ProgrettiDiFacturazione.Name Date = progret.ProgrettiDiFacturazione.Date, ... }, ... }) .ToList(); 

DbSet实现了IQueryable,因此您不需要AsQueryable

如果你已经正确设计了一对多(多对多?)类,那么entity framework足够聪明,可以理解为此需要哪些表连接。 如果没有从该表请求属性,它将不会连接表。