EF核心可选柱按要求处理

时间:2019-03-15 23:50:46

标签: c# sql-server entity-framework ef-core-2.0

我需要从EF Core调用的存储过程中读取结果,该过程包括用于电子表格格式化的内容,例如只有空值的行。我的代码大部分都可以运行,但是有两列会在我包含它们时导致查询失败。

这是我的模型课(为简洁起见,仅包括一些道具):

public class StoredProcRecord
{
    [Column("Prod Line")]
    public string ProductLine { get; set; }

    [Column("Current Sales")]
    public decimal? CurrentSales { get; set; }

    [Column("Current Margin $")]
    public decimal? CurrentMargin { get; set; }
}

如果我从SQL Server Management Studio运行存储过程,则这是输出的一部分:

Stored Proc Output

这是我在db上下文中通过EF Core将类型注册为实体模型的方式:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Query<StoredProcRecord>();
}

这是我调用存储过程的方式:

return _context.Query<StoredProcRecord>().FromSql("EXECUTE my_stored_proc").ToList();

在此示例中,EF Core在尝试通过以下消息调用FromSql()时始终抛出异常:

  

结果中未显示必填列“当前保证金$”   “ FromSql”操作的结果。

根据EF Core docs,只要一列是可为空的,则不需要。但是,我收到要求“当前保证金$”的例外情况。它也仅在使用相同类型的CurrentMargin属性而不是CurrentSales属性下发生。如果我删除CurrentMargin,那么整个程序就可以正常工作,而我只是缺少该属性。

我尝试使用[Column(Order = 2)]代替命名列,以为列名称中的美元符号可能与此有关,但结果是:

  

的结果中没有所需的列“ CurrentMargin”   “ FromSql”操作。

同时包含顺序和名称会导致相同类型的错误。

值得注意的是,这不是我可以选择对其进行更新的存储过程。

CurrentMargin相比,CurrentSales属性有什么不同,导致它像这样失败?我需要使用某些特殊方式来处理列名称中的美元符号吗?我是否完全想念其他东西?

编辑:

这是存储过程的最后一个片段,输出结果表。我将其包括在内是为了表明“当前保证金$”确实是列名称之一。我实际上是从存储过程中直接复制/粘贴了,以确保我没有误输入列名。

BEGIN
-- bulk of stored procedure that builds #tmp_tbl omitted for length
SELECT 
'Prod Line'          = pl_key,
'Current Sales'      = curr_sales,
'Current Margin $'   = curr_margin
FROM #tmp_tbl
END

1 个答案:

答案 0 :(得分:1)

The embarrassing answer to this question is make sure you read your code carefully, especially things like string values.

In this case, I have two stored procedures that will eventually get used by my app, bv_xls_profit_sum_v2 and bv_xls_prod_sum_v2. I was implementing usage of the results of the first stored procedure, but I accidentally provided the name of the second stored procedure to EF. The columns from those two do not match, so the error I was receiving about missing required column wasn't about whether or not the column was nullable, but was actually a case where the column was indeed missing from the result set completely. This wasn't obvious when testing through SQL Server Management Studio because I didn't realize I was running a different stored procedure.

Bonus "Answer":

Prior to figuring out my stupid mistake, I did figure out a workaround that I'll leave here just in case it proves useful for anyone. My app has its own SQL Server instance, but also queries against another SQL Server instance that is not controlled by the app (that's where the stored procedures in question live). To work around the issue I was struggling with, I connected the other SQL Server instance to mine as a linked server. I then duplicated the stored procedure I wanted to call, updated it to have it query the linked server, eliminate unwanted null rows, and return using column names to match my model class. This does work and allows me to manage the stored procedure, though it does likely add additional latency to getting a result set back from querying the modified stored procedure.