选择中的实体框架条件

时间:2014-12-30 14:30:40

标签: c# linq entity-framework

我有以下数据库代码:

static IEnumerable<dynamic> GetData(bool withchildren) {
    using (var model = new testEntities()) {
        var res = default(IQueryable<dynamic>);
        if (withchildren) {
            res = model.UserSet
                .Where(u => u.name != "")
                .Select(u => new {
                    Name = u.name,
                    Email = u.email,
                    Groups = u.GroupSet.Select(g => new {
                        Name = g.name,
                        Id = g.Id
                    })
                });
        } else {
            res = model.UserSet
                .Where(u => u.name != "")
                .Select(u => new {
                    Name = u.name,
                    Email = u.email
                });
        }
        return res.ToList()
    }
}

我想缩小代码并将其写成:

static IEnumerable<dynamic> GetData(bool withchildren) {
    using (var model = new testEntities()) {
        var res = default(IQueryable<dynamic>);
        res = model.UserSet
            .Where(u => u.name != "")
            .Select(u => {
                dynamic item = new { 
                    Name = u.name,
                    Email = u.email
                };
                if(withchildren) {
                    item.Groups = u.GroupSet.Select(g => new {
                        Name = g.name,
                        Id = g.Id
                    });
                }
                return item;
            });
        return res.ToList();
    }
}

但Visual Studio抱怨说,它无法将lambda表达式转换为表达式树。

我的问题是,有没有办法通过实体框架和Linq实现这一目标?我真的不想直接使用ADO.net。

也许甚至有一个更好的版本来缩小它,而不是我想象的代码。

Here是与Linq-To-Objects相关的问题。

修改

在有人要求之前,我在示例代码中使用dynamic来使其更容易和更快。

编辑2

我的目标是,只查询我需要提高性能的字段。检查http://www.progware.org/Blog/post/Slow-Performance-Is-it-the-Entity-Framework-or-you.aspx

目前我们使用

之类的东西
static IEnumerable<dynamic> GetData(bool withchildren) {
    using (var model = new testEntities()) {
        var res = default(IQueryable<dynamic>);
        res = model.UserSet
            .Where(u => u.name != "")
            .ToList();
        return res;
    }
}

根据Glimpse的说法,表现很糟糕。

编辑3

简短的说明,我编写了一些快速而脏的代码。也就是说,为什么不需要最后foreach。目前还没有实际的代码。

2 个答案:

答案 0 :(得分:2)

你有什么理由不能使用:

res = model.UserSet
    .Where(u => u.name != "")
    .Select(u =>  new { 
            Name = u.name,
            Email = u.email,
            Groups = withchildren 
                ? u.GroupSet.Select(g => new {
                     Name = g.name,
                     Id = g.Id
                  })
                : null;
            })
        };

或者也许:

res = model.UserSet
    .Where(u => u.name != "")
    .ToList()                        // ToList() here to enumerate the items
    .Select(u => {
        dynamic item = new { 
            Name = u.name,
            Email = u.email
        };
        if(withchildren) {
            item.Groups = u.GroupSet.Select(g => new {
                Name = g.name,
                Id = g.Id
            });
        }
        return item;
    });

允许您消除某些代码的一种方法是:

var res = model.UserSet.Where(u => u.name != "");
if (withchildren) {
    res = res.Select(u => new {
             Name = u.name,
             Email = u.email,
             Groups = u.GroupSet.Select(g => new {
                Name = g.name,
                Id = g.Id
             })
          });
} else {
    res = res.Select(u => new {
            Name = u.name,
            Email = u.email
        });
}

答案 1 :(得分:1)

社区功能最受欢迎的功能之一是支持EF中的多行表达式, 但到目前为止,您只能使用条件运算符&#34;?:&#34;以及包装结果 一种常见类型,因此您的结果都必须包含&#34;群组&#34;字段。

此外还有linq-providers的扩展,例如https://www.nuget.org/packages/LinqKit/, 但是它们基于自己的惯例,因此任何开发人员都应该深入研究它 提前申请并支持在扩展名上编写的代码。