实体框架 SqlQuery 可以为 null 的字段

Entity Framework SqlQuery Nullable Fields

提问人:Hadi Mohammadi 提问时间:1/4/2019 最后编辑:marc_sHadi Mohammadi 更新时间:1/5/2019 访问量:446

问:

我正在使用实体框架来获取数据。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 的列变成空列。但是当我在存储过程中删除这些列时,一切正常。NullNullNull

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
C# SQL SQL 服务器 实体框架

评论

0赞 MrVoid 1/4/2019
你得到的错误是什么,或者你想实现什么
0赞 Kevin LaBranche 1/4/2019
您需要共享存储过程中的 sql,以便我们提供帮助。
0赞 Kevin LaBranche 1/4/2019
无论 StartDate 和 EndDate 是什么,您都打算返回 null InsertDates?
0赞 Kevin LaBranche 1/4/2019
StartDate 或 EndDate 参数是否可以为 null,如果是,在这种情况下,您想要什么,仅查找 null InsertDates 或忽略该参数?
0赞 Hadi Mohammadi 1/4/2019
@klabranche,并且可以为 null,我只希望它们用于获取开始和结束日期范围内的数据。我加了.谢谢StartDateEndDateStored Procedure

答:

0赞 NaDeR Star 1/4/2019 #1

过程需要返回模型中的所有属性(同名)。如果 procedure 返回任何其他字段,并且您的模型需要它们,则将收到错误。

该查询返回历史记录中的所有行,并根据条件对存储进行权限联接。如果存储中没有匹配的记录,则历史记录中的记录仍包含在记录集中。您可能需要 INNER JOIN。

似乎 EF(至少在某一点)返回了 null 行。 因此,与其选择 *,不如显式命名列,并确保 PK(或其他列)排在第一位。

注意: 我认为几乎总是可以避免 RIGHT JOIN;使用 LEFT JOIN 的查询更易于阅读和理解。

评论

0赞 Kevin LaBranche 1/4/2019
这些属性似乎是正确的,因为用户指出,如果它们删除 null insertdates,则查询将起作用。
0赞 Hadi Mohammadi 1/4/2019
@NaDeR-Star,我返回所有属性,就像MyModel
0赞 Kevin LaBranche 1/4/2019 #2
WHERE (@StartDate IS NULL OR DATEDIFF(DAY,InsertDate,@StartDate) <= 0 )
   AND (@EndDate IS NULL OR DATEDIFF(DAY,InsertDate,@EndDate) >= 1)

当参数为 null 时,会忽略它们。但是,这仍然不能处理 null 。 将为 null 返回 null 。InsertDatesDATEDIFFInsertDates

如果要返回所有 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))

出于性能原因,您可能还需要考虑将语法替换为普通的日期比较语法。 会更快,特别是如果上面有索引。我还相信这种语法可以更清楚地表明您正在查找这些参数日期之间的内容,或者使用将其转换为 >= & <= 语法的内置语法。DATEDIFFInsertDate >= @StartDateInsertDateInsertDatesbetween

在添加 SP SQL 和回答问题之前:

如果没有底层 sql,我们在帮助您方面有点盲目,我们也需要更多的信息。我问了几个问题(在上面的问题评论中),这将有助于我们更清楚地理解:

撇开这一点不谈:

我假设您正在对 和 进行范围/之间。由于这些参数是传入日期的,因此如果您正在执行正常的范围/之间的语法,例如 OR ,则永远不会找到 null,因为 NULL 永远不会等于日期,只有当 or 为 NULL 时。InsertDate@StartDate@EndDateInsertDate >= @StartDateInsertDate 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@EndDateInsertDate >= @StartDate

它必须看起来更像.(@StartDate is null or InsertDate >= @StartDate)

必须对参数执行相同的操作。@EndDate