Entity framework 使用entity framework 5.0重写递归sql select

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

我想得到父模块为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 
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,然后自己继续写。