提问人:Hadi Mohammadi 提问时间:1/4/2019 最后编辑:marc_sHadi Mohammadi 更新时间:1/5/2019 访问量:446
实体框架 SqlQuery 可以为 null 的字段
Entity Framework SqlQuery Nullable Fields
问:
我正在使用实体框架来获取数据。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
Null
UPDATE:这是存储过程
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
答:
过程需要返回模型中的所有属性(同名)。如果 procedure 返回任何其他字段,并且您的模型需要它们,则将收到错误。
该查询返回历史记录中的所有行,并根据条件对存储进行权限联接。如果存储中没有匹配的记录,则历史记录中的记录仍包含在记录集中。您可能需要 INNER JOIN。
似乎 EF(至少在某一点)返回了 null 行。 因此,与其选择 *,不如显式命名列,并确保 PK(或其他列)排在第一位。
注意: 我认为几乎总是可以避免 RIGHT JOIN;使用 LEFT JOIN 的查询更易于阅读和理解。
评论
MyModel
WHERE (@StartDate IS NULL OR DATEDIFF(DAY,InsertDate,@StartDate) <= 0 )
AND (@EndDate IS NULL OR DATEDIFF(DAY,InsertDate,@EndDate) >= 1)
当参数为 null 时,会忽略它们。但是,这仍然不能处理 null 。 将为 null 返回 null 。InsertDates
DATEDIFF
InsertDates
如果要返回所有 null 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,我们在帮助您方面有点盲目,我们也需要更多的信息。我问了几个问题(在上面的问题评论中),这将有助于我们更清楚地理解:
撇开这一点不谈:
我假设您正在对 和 进行范围/之间。由于这些参数是传入日期的,因此如果您正在执行正常的范围/之间的语法,例如 OR ,则永远不会找到 null,因为 NULL 永远不会等于日期,只有当 or 为 NULL 时。InsertDate
@StartDate
@EndDate
InsertDate >= @StartDate
InsertDate between @StartDate and @EndDate
@StartDate
@EndDate
如果您希望返回所有 null,则必须在查询中添加如下内容:InsertDates
select field1,field2 from table1
where (InsertDate is null) or (InsertDate >= @StartDate and InsertDate <= @EndDate)
如果 or 为 null,并且您希望这意味着忽略该参数,则必须在存储过程中重写基础 SQL 以处理更多。@StartDate
@EndDate
InsertDate >= @StartDate
它必须看起来更像.(@StartDate is null or InsertDate >= @StartDate)
必须对参数执行相同的操作。@EndDate
评论
StartDate
EndDate
Stored Procedure