Linq to SQL可空int?

3
我有以下的linq查询(非常简单):
var jobs = from j in db.jobmsts
    join jd in db.jobdtls on j.jobdtl_id equals jd.jobdtl_id
    where j.jobmst_type != 1 && j.jobmst_prntid.Equals(folder.FolderID)
    orderby j.jobmst_name
    select new
        {
            JobID = j.jobmst_id,
            JobName = j.jobmst_name,
            Description = j.jobmst_desc,
            Source = jd.Source
        };

folder.FolderID是可空整型(int?),作为参数传递给方法。所以,当它为null时,查询不返回任何结果。但如果我在TSQL中执行相同的查询:

select * from jobmst j 
join jobdtl jd on j.jobdtl_id = jd.jobdtl_id 
where j.jobmst_type != 1 and j.jobmst_prntid is null

我得到了6个记录。奇怪的是,如果我在linq代码中用"null"替换"folder.FolderID",它确实会返回6条记录。显然,在一个空值对象和"null"之间有区别。我不知道这是什么区别以及如何修复它。
顺便提一下,我的代码中where子句是这样的:
where j.jobmst_type != 1 && j.jobmst_prntid == folder.FolderID

但是它也没有产生任何结果。

任何帮助都将不胜感激。


当您执行该linq时,SQL Profiler会显示什么? - Sam Axe
此外 - 您正在构建一个 Linq 查询对象,但在您与我们分享的代码中尚未执行它。 - Sam Axe
1
请查看以下内容:https://dev59.com/CHRB5IYBdhLWcg3wkH9N - nxu
我不熟悉SQL Profiler。db对象是添加到我的项目中的DataClasses1DataContext对象。 - Chewdoggie
db.log 的输出为 "WHERE ([t0].[jobmst_type] <> @p0) AND ([t0].[jobmst_prntid] = @p1)"。 - Chewdoggie
p0: 输入整数 (大小 = -1; 精度 = 0; 刻度 = 0) [1] p1: 输入整数 (大小 = -1; 精度 = 0; 刻度 = 0) [空值] - Chewdoggie
3个回答

3
如我在评论中已经提到的那样:Linq to Sql中比较可空类型 这个问题的答案也适用于这里:当查询可空类型时,Linq to SQL的行为有些奇怪。解决方案是如果可空类型的值为null,则明确检查null。如果您不想编写两个查询,请编写不同的where子句(您必须混合一些lambda语法):
Expression<Func<Job,bool>> predicate;
if(folder.FolderID == null) {
    predicate = j=>j.jobmst_prntid == null && j.jobmst_type != 1;
} else {
    predicate = j=>j.jobmst_prntid == folder.FolderID && j.jobmst_type != 1;
}

//...
.Where(predicate)
select new
{
    // ...
}

2

我认为当你的值为null时,你需要在表达式中加上(int ?)才能正常工作。

j.jobmst_prntid.Equals ( folder.FolderID )
j.jobmst_prntid.Equals ( (int ? ) folder.FolderID )

更多参考资料请查看:https://msdn.microsoft.com/zh-cn/library/bb882535.aspx,或者您可以尝试以下内容:
 where j.jobmst_type != 1 && j.jobmst_prntid.Equals(folder.FolderID== null ?   null : folder.FolderID)

那个语法是用于连接语句中的可空值。我的问题在于where子句中的可空值。我尝试了这个语法,但它没有起作用。谢谢。 - Chewdoggie

0

针对我的情况,我最终做了这个:

List<Job> folderJobs = new List<Job>();
var tidalJobs = (dynamic) null;
if (folder.FolderID == 0)
{
    tidalJobs = from 
                    master in tidal.jobmsts
                join
                    detail in tidal.jobdtls
                on
                    master.jobdtl_id equals detail.jobdtl_id
                where 
                    master.jobmst_prntid.HasValue == false && master.jobmst_type != 1
                select new
                {
                    JobID = master.jobmst_id,
                    JobName = master.jobmst_name,
                    Description = master.jobmst_desc == null ? string.Empty : master.jobmst_desc,
                    Source = detail.jobdtl_cmd == null ? string.Empty : detail.jobdtl_cmd
                };
}
else
{
    tidalJobs = from
                    master in tidal.jobmsts
                join
                    detail in tidal.jobdtls
                on
                    master.jobdtl_id equals detail.jobdtl_id
                where 
                    master.jobmst_prntid == folder.FolderID && master.jobmst_type != 1
                select new
                {
                    JobID = master.jobmst_id,
                    JobName = master.jobmst_name,
                    Description = master.jobmst_desc == null ? string.Empty : master.jobmst_desc,
                    Source = detail.jobdtl_cmd == null ? string.Empty : detail.jobdtl_cmd
                };
}

foreach (var folderJob in tidalJobs)
{
    ...
}

简而言之,var tidalJobs = (dynamic) null 和 .HasValue == false 是我需要让它工作的东西。唯一的注意事项是将 var 设置为 (dynamic) null 会禁用智能感知,因为所有内容都在运行时评估。所以,你的打字必须非常准确。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接