如何从除某些列之外的表记录中进行选择

本文关键字:记录 选择 行选 | 更新日期: 2023-09-27 18:32:31

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

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

例如,真正的代理表包含大约 10 列,我需要显示所有,不包括"id"。如果我对每 8 列执行相同的操作,则成为一行长而毫无意义的行。如何做到更忘乎所以和好。

如何从除某些列之外的表记录中进行选择

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

  1. 同意在结果集中拥有 ID,或者
  2. 包括Select中除 ID 之外的所有列,或者
  3. 使用映射库,如自动映射程序。

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>();
}

延伸阅读
使用选择除非您懒得键入

为什么不使用自动映射器将实体对象转换为域对象?

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

代理Dto 将包含除"Id"之外的所有字段

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

例如:

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

    从 l in 课程选择"新建"{ l.Id, l.描述, l.LanguageId,
    l.创建于}

有生成的 SQL :

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

    从 l in 课程选择"新建"{ l.创建于}

有生成的 SQL :

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

毕竟,您可以在dataGridView中隐藏一列。

如果您不想写入匿名对象,则可以使用 AutoMapper 作为 @Maruthu Chandrasekaran建议道。

这样,您将能够服务器化解 linq 查询并将其映射到一行中的对象,而不会产生匿名对象的抖动。您也可以创建 DTO 对象。将 Entity-EntityDto 映射与 AutoMapper 结合使用是一项简单的工作。