EF Core 使用空引用执行存储过程

EF Core executing stored procedure with null reference

执行存储过程会在 EF Core 2.0 中产生此错误。我对这个错误不知所措。有什么指点吗?

public class SalesDTO :  BaseEntity
{
    public int SalesID { get; set; }
    [Display(Name = "User")]
    public string SalesRep { get; set; }
    [Display(Name = "Sales Date")]
    public DateTime OrderDate { get; set; }
    public string CustomerName { get; set; }
    public int? CustomerID { get; set; }
    [Display(Name = "Sale Center")]
    public string CenterName { get; set; }
    public int CenterID { get; set; }
    public decimal TotalAmount { get; set; }
    public SalesType SalesType { get; set; }
}

存储过程的模型 class。

这是我的实现class

public IEnumerable<SalesDTO> GetSales(int centerID, string user)
{
        string salesRep = user ?? "";

        List<SqlParameter> parms = new List<SqlParameter>
        {
            new SqlParameter("@CenterID", centerID),
            new SqlParameter("@SalesRep", salesRep)
        };

        return DataContext.Set<SalesDTO>().FromSql("spSalesList @CenterID, @SalesRep", parms.ToArray())
                 .Select(x => new SalesDTO
                 {
                     Id = x.SalesID,
                     SalesID = x.SalesID,
                     CustomerID = x.CustomerID,
                     CustomerName = x.CustomerName,
                     SalesType = x.SalesType,
                     TotalAmount = x.TotalAmount,
                     SalesRep = x.SalesRep,
                     CenterName = x.CenterName,
                     OrderDate = x.OrderDate,
                     CenterID = x.CenterID
                 }).AsNoTracking().ToList();
    }

此代码抛出:

NullReferenceException: Object reference not set to an instance of an object.

使用此堆栈跟踪

但是,如果我使用 SQL 服务器分析器,当我将执行的内容复制回 SQL Server Management Studio 并执行它时,我可以看到存储过程成功执行。

请你试试下面的代码。

return DataContext.Set<SalesDTO>().FromSql($"EXECUTE spSalesList {centerID} {salesRep}")
             .Select(x => new SalesDTO
             {
                 Id = x.SalesID,
                 SalesID = x.SalesID,
                 CustomerID = x.CustomerID,
                 CustomerName = x.CustomerName,
                 SalesType = x.SalesType,
                 TotalAmount = x.TotalAmount,
                 SalesRep = x.SalesRep,
                 CenterName = x.CenterName,
                 OrderDate = x.OrderDate,
                 CenterID = x.CenterID
             }).AsNoTracking().ToList();

同时,了解这些限制是值得的: https://docs.microsoft.com/en-us/ef/core/querying/raw-sql#limitations

我刚刚意识到存储库工作正常,只是数据分辨率问题。

如果您在 .Select 中使用一个 属性 来匹配 2 个不同的属性,则会生成 NULL 引用错误。 所以这个

return DataContext.Set<SalesDTO>().FromSql("spSalesList @CenterID, @SalesRep, @DateFrom, @DateTo", parms.ToArray())
                 .Select(x => new SalesDTO
                 {
                     Id = x.SalesID,
                     SalesID = x.SalesID,
                     CustomerID = x.CustomerID,
                     CustomerName = x.CustomerName,
                     SalesType = x.SalesType,
                     TotalAmount = x.TotalAmount,
                     SalesRep = x.SalesRep,
                     CenterName = x.CenterName,
                     OrderDate = x.OrderDate,
                     CenterID = x.CenterID
                 }).AsNoTracking().ToList();

将给出空引用错误,因为 SalesID 与 SalesID 列和 Id 列都匹配,尽管它可能是同一字段。 但是,当您将代码更改为

return DataContext.Set<SalesDTO>().FromSql("spSalesList @CenterID, @SalesRep, @DateFrom, @DateTo", parms.ToArray())
                 .Select(x => new SalesDTO
                 {
                     Id = x.Id,
                     SalesID = x.SalesID,
                     CustomerID = x.CustomerID,
                     CustomerName = x.CustomerName,
                     SalesType = x.SalesType,
                     TotalAmount = x.TotalAmount,
                     SalesRep = x.SalesRep,
                     CenterName = x.CenterName,
                     OrderDate = x.OrderDate,
                     CenterID = x.CenterID
                 }).AsNoTracking().ToList();

然后它可以正常工作,因为 Id 和 SalesID 与不同的字段匹配。我还不明白为什么会这样。 等我明白了再补充。