实体框架SqlQuery可空字段

时间:2019-01-04 14:26:01

标签: c# sql sql-server entity-framework

我正在使用实体框架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

2 个答案:

答案 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)

参数为空时会忽略它们。但是,它仍然不能处理空InsertDatesDATEDIFF将返回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 >= @StartDateInsertDate 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)参数必须执行相同的操作。