左外连接 linq 查询对象引用未设置为对象的实例
Left outer join linq query object reference not set to an instance of an object
我有三个 table,我对两个 table 执行了内部连接,而不是左外部连接
为什么下面的查询返回这个错误
"linq query object reference not set to an instance of an object"
var model = from p in Uow.Instance.RepoOf<RoleMenuMetrix>().GetAll()
from n in Uow.Instance.RepoOf<NavigationMenu>().GetAll().Where(q => q.Id == p.MenuId)
from m in
Uow.Instance.RepoOf<NavigationButton>()
.GetAll()
.Where(q => q.NavigationMenuId == n.Id)
.DefaultIfEmpty()
where p.RoleId == Guid.Parse("96246E99-6BF2-4A3D-8D2C-263DDEF2F97B")
&& n.IsActive && n.ApplicationName == "MEM"
select new
{
p.MenuId,
p.RoleId,
n.Name,
n.ParentId,
ButtonName = m.ButtonName == null ? "" : m.ButtonName // when i comment this it works fine
};
linqPad 中的以下查询工作正常
from p in P_RoleMenuMetrixes
from n in NavigationMenus.Where(q => q.Id == p.MenuId)
from m in NavigationButtons.Where(q => q.NavigationMenuId == n.Id).DefaultIfEmpty()
where p.RoleId == Guid.Parse("96246E99-6BF2-4A3D-8D2C-263DDEF2F97B")
&& n.IsActive && n.ApplicationName == "MEM"
select new
{
p.MenuId,
p.RoleId,
n.Name,
n.ParentId,
m.ButtonName
}
错误截图
当你使用 DefaultIfEmpty 时,如果没有找到匹配项,则会分配默认值,因此你需要检查 null
并分配适当的值,如下所示:-
ButtonName = m!= null ? m.ButtonName : String.Empty
我在这里考虑 ButtonName
是 string
如果不是,您可以相应地更改查询。
你需要检查空值,使用下面的代码
ButtonName = m== null ? "": m.ButtonName
该错误表明您的代码中存在更严重的缺陷。 LINQ 语句不会转换为一个 SQL 语句(就像您在 Linqpad 中执行的 LINQ),而是三个单独的语句,其结果在内存中连接。所以它只是 LINQ to objects。因此空引用。
您的 UoW/Repo 架构需要重大修改!您已禁用 LINQ 语句的可组合性。 GetAll()
不应该 return a List<T>
(如屏幕截图所示),而是 IQueryable<T>
,即 DbSet
.
目前,GetAll()
将始终将整个 table 提取到内存中。您之后进行的任何过滤都不会影响 SQL 语句。
我有三个 table,我对两个 table 执行了内部连接,而不是左外部连接 为什么下面的查询返回这个错误 "linq query object reference not set to an instance of an object"
var model = from p in Uow.Instance.RepoOf<RoleMenuMetrix>().GetAll()
from n in Uow.Instance.RepoOf<NavigationMenu>().GetAll().Where(q => q.Id == p.MenuId)
from m in
Uow.Instance.RepoOf<NavigationButton>()
.GetAll()
.Where(q => q.NavigationMenuId == n.Id)
.DefaultIfEmpty()
where p.RoleId == Guid.Parse("96246E99-6BF2-4A3D-8D2C-263DDEF2F97B")
&& n.IsActive && n.ApplicationName == "MEM"
select new
{
p.MenuId,
p.RoleId,
n.Name,
n.ParentId,
ButtonName = m.ButtonName == null ? "" : m.ButtonName // when i comment this it works fine
};
linqPad 中的以下查询工作正常
from p in P_RoleMenuMetrixes
from n in NavigationMenus.Where(q => q.Id == p.MenuId)
from m in NavigationButtons.Where(q => q.NavigationMenuId == n.Id).DefaultIfEmpty()
where p.RoleId == Guid.Parse("96246E99-6BF2-4A3D-8D2C-263DDEF2F97B")
&& n.IsActive && n.ApplicationName == "MEM"
select new
{
p.MenuId,
p.RoleId,
n.Name,
n.ParentId,
m.ButtonName
}
错误截图
当你使用 DefaultIfEmpty 时,如果没有找到匹配项,则会分配默认值,因此你需要检查 null
并分配适当的值,如下所示:-
ButtonName = m!= null ? m.ButtonName : String.Empty
我在这里考虑 ButtonName
是 string
如果不是,您可以相应地更改查询。
你需要检查空值,使用下面的代码
ButtonName = m== null ? "": m.ButtonName
该错误表明您的代码中存在更严重的缺陷。 LINQ 语句不会转换为一个 SQL 语句(就像您在 Linqpad 中执行的 LINQ),而是三个单独的语句,其结果在内存中连接。所以它只是 LINQ to objects。因此空引用。
您的 UoW/Repo 架构需要重大修改!您已禁用 LINQ 语句的可组合性。 GetAll()
不应该 return a List<T>
(如屏幕截图所示),而是 IQueryable<T>
,即 DbSet
.
目前,GetAll()
将始终将整个 table 提取到内存中。您之后进行的任何过滤都不会影响 SQL 语句。