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 与不同的字段匹配。我还不明白为什么会这样。
等我明白了再补充。
执行存储过程会在 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 与不同的字段匹配。我还不明白为什么会这样。 等我明白了再补充。