实体框架 - 仅从列表中获取动态指定的特定列

时间:2015-08-12 14:54:50

标签: linq entity-framework linq-to-sql entity-framework-6 linq-expressions

我希望有一些灵活性并提供一些接口来指定应该动态包含在最终选择中的列列表。

例如此表

    public class Person
    {
        [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity), Key()]
        public int Id { get; set; }

        [Required]
        public string FirstName { get; set; }

        [Required]
        public string LastName { get; set; }

        public string Address { get; set; }

        ...
    }

我希望有一个案例

persons.Select(p => new { FirstName = p.FirstName, LastName = p.LastName }).ToList();

但在另一个我想要

persons.Select(p => new { FirstName = p.FirstName, LastName = p.LastName, Address = p.Address }).ToList();

在第三种情况下,我还需要其他东西......所以,我认为有一些灵活的机制可以指定要提取的列列表。

我有什么想法可以做到这一点吗?

我正在阅读一些有关LINQ表达式的内容,我有一些感觉这是正确的方法,但不明白它是如何实现的......

3 个答案:

答案 0 :(得分:1)

如果你包含NuGet包System.Linq.Dynamic,它非常简单:

var columns = new [] { "FirstName", "LastName" };
var selectText = "new (" + string.Join(", ", columns) + ")";
var result = Users.AsQueryable().Select(selectText);

或者类型安全

var columns = new Expression<Func<User, object>> [] { x => x.FirstName, x => x.Surname };
var selectText = "new (" + string.Join(", ", columns.Select(x => ((MemberExpression)x.Body).Member.Name)) + ")";
var result = Users.AsQueryable().Select(selectText);

这会将表达式转换为字符串,以便将它们转回来,因此它不是最优化的方法,但与数据库查询相比,成本可能微不足道。

你可以通过构建表达式来实现它,但是库可以为你完成所有这些。

答案 1 :(得分:0)

基本上,这是你正确的做法。你只能通过使用类作为&#39;模型&#39;来使它更舒适并且类型安全。为您的数据。基本上,创建另一个Person类,其中包含表格的所有字段,或者仅包含您在该人员中所需的字段#39;。这样做而不是仅仅创建无名对象并将它们写入列表可以提供更大的灵活性,因为您可以添加其他方法来转换此类中的数据。

您还可以根据要初始化的字段向此类添加不同的构造函数。像这样:

var modelPersons = persons.Select(p => new ModelPerson(p.FirstName, p.LastName)).ToList();

如果为所需的每次初始化编写构造函数,则在查询时您将拥有可重用和短代码。当然,你仍然可以使用像这样的对象初始化器:

var modelPersons = persons.Select(p => new ModelPerson {
  FirstName = p.FirstName
  LastName = p.LastName
}).ToList();

与您发布的那个一样长,但最好使用您可以自己定义的对象,添加方法,格式化数据等。但是,您只需要使用正确的方法。< / p>

答案 2 :(得分:0)

扩展Mant101的答案。您可以使用extern alias解决重复的命名空间问题。另请参阅this answer至SO问题。