我正在使用实体框架SqlQuery
来获取数据。
代码如下:
Context.Database.SqlQuery<MyModel>("exec dbo.MySP @StartDate, @EndDate", Params.ToArray()).ToListAsync();
和MyModel
类
public class MyModel
{
public int? Code{ get; set; }
public string Name{ get; set; }
public DateTime? InsertDate { get; set; }
}
问题是当我的存储过程结果中有一些Null
列时,可空列在所有行中都变成Null
。但是,当我删除存储过程中的Null
列时,一切正常。
更新:这是存储过程
ALTER PROCEDURE [dbo].[MySP]
@StartDate DATETIME = NULL,
@EndDate DATETIME = NULL
AS
BEGIN
CREATE TABLE #LastUpdates (Code INT, InsertDate DATETIME)
SET NOCOUNT ON;
INSERT INTO #LastUpdates
SELECT
StoreCode,
MAX(InsertDate)
FROM
[dbo].[History]
WHERE
(@StartDate IS NULL OR DATEDIFF(DAY, InsertDate, @StartDate) <= 0 )
AND (@EndDate IS NULL OR DATEDIFF(DAY, InsertDate, @EndDate) >= 1)
GROUP BY
StoreCode
SELECT DISTINCT
store.Name as Name,
store.Code as Code,
Updates.InsertDate AS InsertDate
FROM
#LastUpdates AS Updates
RIGHT JOIN
[Stores] AS store ON Updates.Code = store.Code
WHERE
store.IsDeleted = 0
DROP TABLE #LastUpdates
END
答案 0 :(得分:0)
您的过程需要返回模型中的所有属性(相同名称)。如果procedure返回任何其他字段,并且您的模型期望它们,您将得到错误。
该查询返回历史记录中的所有行,并根据条件在商店上进行右连接。如果商店中没有记录匹配,则历史记录中的记录仍包含在记录集中。您可能需要INNER JOIN。
似乎EF(至少在某一点)返回了空行。 因此,与其选择*,您应该显式命名列,并确保PK(或其他列)在首位。
注意: 我认为几乎总是可以避免RIGHT JOIN;使用LEFT JOIN查询更容易阅读和理解。
答案 1 :(得分:0)
WHERE (@StartDate IS NULL OR DATEDIFF(DAY,InsertDate,@StartDate) <= 0 )
AND (@EndDate IS NULL OR DATEDIFF(DAY,InsertDate,@EndDate) >= 1)
参数为空时会忽略它们。但是,它仍然不能处理空InsertDates
。 DATEDIFF
将返回null,而null为InsertDates
。
如果您想返回所有空的InsertDates,则需要在其余查询中添加(InsertDate is null) OR
。
WHERE (InsertDate is null) OR ((@StartDate IS NULL OR DATEDIFF(DAY,InsertDate,@StartDate) <= 0 )
AND (@EndDate IS NULL OR DATEDIFF(DAY,InsertDate,@EndDate) >= 1))
出于性能原因,您可能还需要考虑将DATEDIFF
替换为普通的日期比较语法。 InsertDate >= @StartDate
会更快,特别是如果InsertDate
上有索引。我还相信这种语法可以使您更清楚地知道,您正在这些参数日期之间寻找InsertDates
还是使用内置的between
语法将其转换为> =&<=语法。
在添加SP SQL和回答问题之前:
如果没有基础sql,我们会在帮助您方面有点盲目,我们也需要更多信息。我问了几个问题(上面的问题评论中),这些问题可以帮助我们更清楚地理解:
那边:
我假设您正在InsertDate
和@StartDate
和@EndDate
之间做一个范围/介于两者之间的操作。由于这些参数传递的是日期,因此,如果您使用InsertDate >= @StartDate
或InsertDate between @StartDate and @EndDate
之类的常规范围/中间语法,则永远不会找到null,因为NULL永远不会等于日期,只有当@StartDate
或@EndDate
为NULL。
如果您希望返回所有空InsertDates
,则必须在查询中添加以下内容:
select field1,field2 from table1
where (InsertDate is null) or (InsertDate >= @StartDate and InsertDate <= @EndDate)
如果@StartDate
或@EndDate
为空,并且您希望这表示忽略该参数,那么您就必须重写存储过程中的基础SQL,以处理不仅仅是{{1} }。
它看起来必须更像InsertDate >= @StartDate
。
(@StartDate is null or InsertDate >= @StartDate)
参数必须执行相同的操作。