如何从表记录中选择除某些列以外的记录

时间:2014-11-29 18:52:11

标签: c# linq entity-framework datagridview linq-to-entities

我有一个从sql数据库创建的实体数据库。我需要在datagridview上显示记录,我正在使用此代码。

DBEntities db = new DBEntities();
dataGridView1.DataSource = db.Agent.Select(x => new { Name = x.Name, Second_Name = x.Second_Name}).ToList();

这是一个例子,真正的代理表包含大约10列,我需要显示所有,exept'id'。如果我为每8列做同样的事情,那就变成一条长而无意义的行。怎么做更多的遗忘和好。

3 个答案:

答案 0 :(得分:3)

如果您不想使用匿名类型指定所需的字段,您可以:

  1. 在结果集中使用ID,或
  2. 包括Select中除ID或
  3. 之外的所有列
  4. 使用映射库,如AutoMapper。
  5. Linq没有Select Except声明。但是,您可以使用此扩展方法来完成相同的操作:

    /// <summary>
    /// Returns all fields/properties from <paramref name="source"/> except for the field(s)/property(ies) listed in the selector expression.
    /// </summary>
    public static IQueryable SelectExcept<TSource, TResult>( this IQueryable<TSource> source, Expression<Func<TSource, TResult>> selector )
    {
        var newExpression = selector.Body as NewExpression;
    
        var excludeProperties = newExpression != null
                ? newExpression.Members.Select( m => m.Name )
                : new[] { ( (MemberExpression)selector.Body ).Member.Name };
    
        var sourceType = typeof( TSource );
        var allowedSelectTypes = new Type[] { typeof( string ), typeof( ValueType ) };
        var sourceProperties = sourceType.GetProperties( BindingFlags.Public | BindingFlags.Instance ).Where( p => allowedSelectTypes.Any( t => t.IsAssignableFrom( ( (PropertyInfo)p ).PropertyType ) ) ).Select( p => ( (MemberInfo)p ).Name );
        var sourceFields = sourceType.GetFields( BindingFlags.Public | BindingFlags.Instance ).Where( f => allowedSelectTypes.Any( t => t.IsAssignableFrom( ( (FieldInfo)f ).FieldType ) ) ).Select( f => ( (MemberInfo)f ).Name );
    
        var selectFields = sourceProperties.Concat( sourceFields ).Where( p => !excludeProperties.Contains( p ) ).ToArray();
    
        var dynamicSelect = 
                string.Format( "new( {0} )",
                        string.Join( ", ", selectFields ) );
    
        return selectFields.Count() > 0
            ? source.Select( dynamicSelect )
            : Enumerable.Empty<TSource>().AsQueryable<TSource>();
    }
    

    进一步阅读
    Use SelectExcept When You Are Too Lazy to Type

答案 1 :(得分:1)

为什么不使用automapper将实体对象转换为域对象?

Mapper.CreateMap<Agent, AgentDto>();
dataGridView1.DataSource = db.Agent.Select(x => Mapper.Map<AgentDto>(x)).ToList();

AgentDto将包含除了&#39; Id&#39;

之外的所有字段

答案 2 :(得分:0)

这个问题已经回答here,这绝对是可能的。如果不需要的属性可以为空,或者您可以使用匿名,则可以将所选列再次强制转换为原始对象的可枚举。

例如:

  1. 在LINQ Pad中再次测试完整查询真实表

    来自l in Lessons 选择新的 {     盖,     l.Description,     l.LanguageId,
        l.CreatedOn }

  2. 产生了SQL:

    SELECT [t0].[Id], [t0].[Description], [t0].[LanguageId], [t0].[CreatedOn]
    FROM [Lessons] AS [t0]
    
    1. 剪切版本在LINQ Pad中测试,列数较少

      来自l in Lessons 选择新的 {     l.CreatedOn }

    2. 产生了SQL:

      SELECT [t0].[CreatedOn]
      FROM [Lessons] AS [t0]
      

      毕竟you can hide a column in the dataGridView.

      如果您不想编写匿名对象,可以使用AutoMapper作为@ maruthu chandrasekaran建议。

      通过这种方式,您可以将缩减的linq查询服务器并将其映射到一行中的对象,而不会出现匿名对象的抖动。您也可以创建DTO对象。使用Entity-EntityDto与AutoMapper进行映射是一件容易的事。