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 ANSIJOIN
语法-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 Many to Many Relation Mapping(Entity Framework多对多关系映射)