我有一个视图(vw_users)和一个表(CTUsers)。当我从视图中请求数据时,我的sql查询曾经工作过:
var result = (from i in dc.vw_Users
where i.CTid == ctid
select new
{
UserId = i.UserId,
WelcomeSent = (i.WelcomeSent != null && i.WelcomeSent.ToString().Length > 0
? DateTime.Parse(i.WelcomeSent.ToString())
: new DateTime())
});
但是现在我想从表中获取WelcomeSent,所以我使用这段代码:
var result = (from i in dc.vw_Users
join k in dc.CTUsers
on i.CTid equals k.CTid
where i.CTid == ctid
select new
{
UserId = i.UserId,
WelcomeSent = (k.WelcomeSent != null && k.WelcomeSent.ToString().Length > 0
? DateTime.Parse(k.WelcomeSent.ToString())
: new DateTime())
}).Distinct();
但现在当我运行此查询时,我得到了这个错误:
SqlDateTime溢出。必须在1/1/1753 12:00:00 AM之间 12/31/9999 11:59:59 PM
SQL视图和表WelcomeSent类型是DateTime,它也可以是NULL。以下是WelcomeSent的示例值:2017-03-07 00:00:00.000
答案 0 :(得分:0)
这里真正的问题是Distinct()
方法。如果您掌握以SQL格式运行的查询并直接从SSMS运行数据库,它们将运行正常。它是LINQ to SQL,它限制了在使用Distinct()时不允许DateTime值小于某个值。
我不确定为什么你需要在datetime和字符串值之间使用奇怪的来回转换。
以下是在数据库上运行的实际查询。
第一种情况:
SELECT [t0].[Id] AS [TokenId], [t0].[Token],
(CASE WHEN ([t0].[ExpiryDate] IS NOT NULL)
AND ((CONVERT(Int,LEN(CONVERT(NVarChar(MAX),[t0].[ExpiryDate])))) > @p1)
THEN 1
WHEN NOT (([t0].[ExpiryDate] IS NOT NULL)
AND ((CONVERT(Int,LEN(CONVERT(NVarChar(MAX),[t0].[ExpiryDate])))) > @p1))
THEN 0
ELSE NULL
END) AS [value],
CONVERT(NVarChar(MAX),[t0].[ExpiryDate]) AS [s]
FROM [dbo].[TokenView] AS [t0]WHERE [t0].[Id] = @p0
第二种情况:
SELECT DISTINCT [t2].[Id] AS [TokenId], [t2].[Token], [t2].[value], [t2].[value2] AS [s], [t2].[value3]
FROM (
SELECT [t0].[Id], [t0].[Token],
(CASE WHEN ([t1].[ExpiryDate] IS NOT NULL)
AND ((CONVERT(Int,LEN(CONVERT(NVarChar(MAX),[t1].[ExpiryDate])))) > @p0)
THEN 1
WHEN NOT (([t1].[ExpiryDate] IS NOT NULL)
AND ((CONVERT(Int,LEN(CONVERT(NVarChar(MAX),[t1].[ExpiryDate])))) > @p0))
THEN 0
ELSE NULL
END) AS [value],
CONVERT(NVarChar(MAX),[t1].[ExpiryDate]) AS [value2], @p1 AS [value3]
FROM [dbo].[TokenView] AS [t0]
INNER JOIN [dbo].[Tokens] AS [t1] ON [t0].[Id] = [t1].[Id]) AS [t2]
WHERE [t2].[Id] = @p2
我建议使用第二个查询的解决方案来解决问题。
使用查询创建一个可以保存您从数据库中选择的数据的类。
public class MyClass
{
public int Id { get; set; }
public string Token { get; set; }
//Consider this property as WelcomeSent property from your code.
public DateTime? ExpiryDate { get; set; }
//Use this property only to display the data in UI.
public DateTime FormattedExpiryDate
{
get
{
return ExpiryDate != null && ExpiryDate.ToString().Length > 0
? DateTime.Parse(ExpiryDate.ToString())
: new DateTime();
}
}
}
按如下方式更改查询。
var query = (from i in dc.TokenViews //TokenViews is same as vw_Users of yours.
join k in dc.Tokens //Tokens is same as CTUsers
on i.Id equals k.Id
where i.Id == 5 //Hardcoding the selection criteria.
select new MyClass
{
Id = i.Id,
Token = i.Token,
ExpiryDate = k.ExpiryDate //Retrieving values as it is from the db.
}).Distinct();
显示以下值,以查看ExpiryDate和FormattedExpiryDate
之间的差异foreach (var item in query)
{
Console.WriteLine("Id : {0}", item.Id);
Console.WriteLine("Token : {0}", item.Token);
Console.WriteLine("ExpiryDate : {0}", item.ExpiryDate);
Console.WriteLine("FormattedDate : {0}", item.FormattedExpiryDate);
}
您也可以对第一个查询使用相同的方法。这将避免SQL查询中的所有CASE WHEN
子句和CONVERT
。