Entity Framework 的 FromSql 方法执行使用内部连接选择语句的 SQL Server 表值函数

Posted

技术标签:

【中文标题】Entity Framework 的 FromSql 方法执行使用内部连接选择语句的 SQL Server 表值函数【英文标题】:Entity Framework's FromSql method to execute a SQL Server table-valued function that uses an inner join select statement 【发布时间】:2021-07-14 16:11:32 【问题描述】:

Output screenshot

我创建了实体类来匹配函数列,将DbSet包含在上下文类中,并完成了存储库中的方法,但是使用FromSql的函数调用不起作用。

代码如下:

    SQL Server 功能:

     CREATE FUNCTION dbo.ufn_viewInvoices()
     RETURN TABLE
     AS
         RETURN 
             (SELECT 
                  i.InvoiceId, i.CustomerId, c.CompanyName, 
                  c.LastName, a.StreetNumber, a.StreetName, 
                  a.City, i.Revenue, i.DateStarted, i.DateCompleted, 
                  i.DaysEstimate, i.DaysActual
              FROM 
                  Invoices i, Customers c, Addresses a 
              WHERE 
                  i.CustomerId = c.CustomerId 
                  AND i.WorkAddressId = a.AddressId);
    

    我的实体类来匹配函数的select语句中的列:

     public class InvoiceCustomerNameAddresses
     
         [Key] 
         public byte InvoiceId  get; set; 
         public byte CustomerId  get; set; 
         public string CompanyName  get; set; 
         public string LastName  get; set; 
         public string StreetNumber  get; set; 
         public string StretName  get; set; 
         public string City  get; set; 
         public decimal? Revenue  get; set; 
         public DateTime? DateStarted  get; set; 
         public DateTime? DateCompleted  get; set; 
         public byte? DaysEstimate  get; set; 
         public byte? DaysActual  get; set; 
     
    

    DbContext 类中的DbSet

     public  DbSet<InvoiceCustomerNameAddresses> InvoiceCustomerNameAddresses  get; set; 
    

    这是存储库中的方法:

     public List<InvoiceCustomerNameAddresses> GetInvoicesUsingTVF()
     
         List<InvoiceCustomerNameAddresses> invoicesList;
    
         try 
         
             Console.WriteLine("Inside GetInvoicesUsingTVF method in repo, about to call function");
    
             invoicesList = context.InvoiceCustomerNameAddresses.FromSql("SELECT * FROM 
                            [dbo].ufn_viewInvoices()").ToList();
    
             Console.WriteLine("Function called, invoicesList count: " + invoicesList.Count);
         
         catch (Exception)
         
             Console.WriteLine("In repo's catch, so something went wrong");
             invoicesList = null;
             Console.WriteLine("An error occurred");
         
         return invoicesList;
     
    

    控制器中的方法:

     [HttpGet]
     public List<InvoiceCustomerNameAddresses> GetAllInvoicesUsingTVF() 
     
         List<InvoiceCustomerNameAddresses> detailedInvoicesList = null;
         try
         
             Console.WriteLine("Inside controller, about to call the repo's getInvoicesUsingTVF method");
             detailedInvoicesList = invoiceRepository.GetInvoicesUsingTVF();
             Console.WriteLine("Received detailedInvoicesList, count: " + detailedInvoicesList.Count);
         
         catch (Exception)
         
             Console.WriteLine("In catch block, so something went wrong");
             detailedInvoicesList = null;
            
    
         return detailedInvoicesList;
     
    

请注意:

上面代码中的控制台打印输出语句,在使用.FromSql方法调用函数之前和之后:第一个控制台打印输出被执行,但是函数调用语句执行有一个明显的问题,因为下一个被执行的控制台打印输出是catch 块中的那个。

请注意屏幕截图中显示的输出中的“执行 ObjectResult,写入类型为‘null’的值”的行。这反映了 catch 块中的语句:“invoicesLIst = null”(见附图)。

请注意,此函数调用不使用参数,最后,从 SQL Server Management Studio 执行此函数可以正常工作。

问题:我错过了我的 .FromSql 函数调用不起作用?

【问题讨论】:

Bad habits to kick : using old-style JOINs - 旧式 逗号分隔的表格列表 样式已替换为 ANSI 中的 proper ANSI JOIN 语法-92 SQL 标准(差不多 30 年前),不鼓励使用它 谢谢你,@marc_s。我将函数更改为使用 JOIN 。至于我的问题,您能想到 .FromSql 方法不起作用的任何原因吗? 您应该检查您遇到的异常!最有可能的是,它会告诉您出了什么问题,并可能会告诉您如何解决它!不要只报告“发生错误”——输出异常中包含的信息!这就是它的用途! 谢谢。我并没有真正得到错误,只是“未定义”,但那是因为我以这种方式设置了代码。无论如何,我想通了。我在实体类中拼错了 StreetName(取而代之的是 StretName),并且实体的属性名称必须与 Sql Server 函数中 select 语句中的列名称匹配。 【参考方案1】:

我发布这个问题是因为一段时间后,显而易见的事情似乎并不那么明显,多一双眼睛可能有助于了解我所缺少的东西。我没有得到异常,但没有得到我期望的数据(附加的输出截图),因为我有一个拼写错误。实体类中的属性必须与使用 EF 的 FromSql 方法调用的函数中的 select 语句的列名匹配。因此,无法识别上述代码中实体的“StretName”;它应该是“街名”。现在可以正常使用了。

【讨论】:

以上是关于Entity Framework 的 FromSql 方法执行使用内部连接选择语句的 SQL Server 表值函数的主要内容,如果未能解决你的问题,请参考以下文章

Entity Framework Code-First(23):Entity Framework Power Tools

Entity Framework怎么GroupBY多个字段

entity framework 公共类

初步了解Entity Framework

Entity Framework Many to Many Relation Mapping(Entity Framework多对多关系映射)

为啥 Entity framework Entity Master Details Entity Edit