Entity framework 使用entity framework 5.0重写递归sql select
我想得到父模块为null的所有模块,这意味着所有根模块 此外,我希望每个模块都知道它是否有子模块 我需要这个特性,因为根模块显示在延迟加载的模块树中 通过这种方式,它在SQL中运行得很快:Entity framework 使用entity framework 5.0重写递归sql select,entity-framework,c#-4.0,Entity Framework,C# 4.0,我想得到父模块为null的所有模块,这意味着所有根模块 此外,我希望每个模块都知道它是否有子模块 我需要这个特性,因为根模块显示在延迟加载的模块树中 通过这种方式,它在SQL中运行得很快: SELECT Id, CASE WHEN EXISTS (SELECT NULL FROM Module m2 WHERE m2.ParentId = module.Id) THEN 1 ELSE 0 END AS HasChildren FROM Module
SELECT
Id,
CASE WHEN EXISTS (SELECT NULL FROM Module m2 WHERE m2.ParentId = module.Id) THEN 1
ELSE 0
END AS HasChildren
FROM Module
WHERE ParentId IS NULL
如何使用EF 5实现同样的功能
更新
这些是我的类,它们是我的Poco,首先使用EF代码:
public class Module
{
public Module()
{
Children = new List<Module>();
}
// PK
public int ModuleId { get; set; }
public string Name { get; set; }
public List<Module> Children { get; set; }
// FK
public int MachineId { get; set; }
public Machine Machine { get; set; }
}
public class Machine
{
// PK
public int MachineId { get; set; }
public string Name { get; set; }
}
您的linq查询对于HasChildren属性永远不会返回TRUE,因为my formery查询看起来不同:
context.Modules.SqlQuery("SELECT Module.ModuleId, Module.Name, case when Exists(select null from Module m where m.ParentID = Module.ModuleId) " +
"then 1 else 0 end as HasChildren FROM Module WHERE Module.ParentId Is Null AND Module.MachineId = @MachineId ORDER BY HierarchyIndex",
new SqlParameter("MachineId",machineId)).ToList();
在EF生成的“your”sql语句中,我错过了重要的m.ParentId=Module.ModuleId比较。您不需要Extend1.ModuleId=Extend2.Module\u ModuleId
似乎有点不对劲。到目前为止,这两个答案并不能解释EF查询中对CLR方法的调用无法转换为SQL,EF将抛出异常
public void ListModule()
{
var raw= from m1 in db.Module
where m1.ParentId == null
select new { m1.ParentId, wanted = this.test(m1.ParentId) };
}
public int test(string para)
{
var raw = from c in db.Module
where c.ParentId == para
select c;
if (raw.Count() != 0)
return 1;
else
return 0;
}
因此,您必须使用EF可以转换为SQL的方法来解决它。现在幸运的是,您的查询不是递归的(如获取所有层次结构级别),而是非常严格的:
from m in context.Modules
where m.ParentId == null
select new { m.Id, HasChildren = m.Children.Any() }
如你所见,我必须对你的模型做一些假设(这就是为什么我要问)。主要是模块
具有导航属性children
(1:n)。您可以不使用,但必须(分组)加入模块
:
from m in context.Modules.Where(x => x.ParentId == null)
join child in context.Modules on m.Id equals child.ParentId
into groupJoin
select new Node { m.Id, HasChildren = groupJoin.Any() }
(一个
节点
类具有两个get/set属性Id
和haschilds
)。到目前为止,这两个答案并不能解释EF查询中对CLR方法的调用不能转换为SQL,EF将抛出异常
因此,您必须使用EF可以转换为SQL的方法来解决它。现在幸运的是,您的查询不是递归的(如获取所有层次结构级别),而是非常严格的:
from m in context.Modules
where m.ParentId == null
select new { m.Id, HasChildren = m.Children.Any() }
如你所见,我必须对你的模型做一些假设(这就是为什么我要问)。主要是模块
具有导航属性children
(1:n)。您可以不使用,但必须(分组)加入模块
:
from m in context.Modules.Where(x => x.ParentId == null)
join child in context.Modules on m.Id equals child.ParentId
into groupJoin
select new Node { m.Id, HasChildren = groupJoin.Any() }
(使用一个
节点
类,该类具有两个get/set属性Id
和haschilds
)。感谢您修复了糟糕的sql格式问题。我不能让它工作…你能展示一个类模型,也许是第一次努力实现你想要的吗?这样我们就知道从哪里开始了。谢谢你修复了糟糕的sql格式。我不能让它工作…你能展示一个类模型,也许是第一次努力实现你想要的吗?所以我们知道从哪里开始。同意在这里阅读您的答案,然后重新阅读问题,这并不像我第一次处理的那样复杂。@gert我在模块类中放置了一个children属性,但这如何工作?EF从哪里知道如何填充此属性?@Gert我已经用示例代码更新了我的问题,现在我在家里…:)@Elisa EF知道您的模型,因此当您从数据库(例如,通过var module=context.Modules.Find(1)
)获取Id=1的模块时,您可以执行var children=module.children
,EF将通过向数据库发送查询来填充集合(如果上下文仍然存在!)。@Elisa,如果您这样做,应该启用延迟加载。这可以通过将子对象定义为public virtual ICollection
(注意virtual
)来实现。在这里,我同意阅读您的答案,然后重新阅读问题,这并不像我第一次处理的那样复杂。@gert我在模块类中放置了一个children属性,但这如何工作?EF从哪里知道如何填充此属性?@Gert我已经用示例代码更新了我的问题,现在我在家里…:)@Elisa EF知道您的模型,因此当您从数据库(例如,通过var module=context.Modules.Find(1)
)获取Id=1的模块时,您可以执行var children=module.children
,EF将通过向数据库发送查询来填充集合(如果上下文仍然存在!)。@Elisa,如果您这样做,应该启用延迟加载。这可以通过将子项定义为公共虚拟ICollection
(注意虚拟
)来实现。为什么不接受这个答案?您从Levis获得的示例代码。。。现在你用一种可怕的方式把它传给我。。。一个void方法返回原始值?你到底在读什么?我误解了你的问题。我想,你只需要0和1,然后自己继续写。你为什么不接受这个答案?您从Levis获得的示例代码。。。现在你用一种可怕的方式把它传给我。。。一个void方法返回原始值?你到底在读什么?我误解了你的问题。我想,你只需要0和1,然后自己继续写。