简体   繁体   中英

How to Select from table records except some columns

I have a entity database, created from sql database. I need to show record on datagridview, i am using this code.

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

It's example, real agent table contain around 10 columns, and i need to show all, exept 'id'. If i do same for every 8 columns, become a long and senseless row. How to do it more obliviuous and good.

If you don't want to use an anonymous type to specify the fields you want, you can:

  1. Live with having the ID in the result set, or
  2. Include all of the columns in the Select except for the ID, or
  3. Use a mapping library, like AutoMapper.

There's no Select Except statement in Linq. However, you can use this extension method to accomplish the same thing:

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

Further Reading
Use SelectExcept When You Are Too Lazy to Type

Why don't you use automapper to convert the entity object to a domain object?

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

The AgentDto will contain all the fields except 'Id'

This question is answered here and it is definitely possible. You can cast the selected columns again into enumerable of the original object if the undesired properties are nullable or you can use anonymous.

For example :

  1. Full query tested in LINQ Pad agains real table

    from l in Lessons select new { l.Id, l.Description, l.LanguageId,
    l.CreatedOn }

has resulting SQL :

SELECT [t0].[Id], [t0].[Description], [t0].[LanguageId], [t0].[CreatedOn]
FROM [Lessons] AS [t0]
  1. The cut version tested in LINQ Pad with less columns

    from l in Lessons select new { l.CreatedOn }

has resulting SQL :

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

After all that you can hide a column in the dataGridView.

If you do not want to write the anonymous object you can use AutoMapper as @ maruthu chandrasekaran suggested.

This way you will be able to server your linq query reduced and map it to your object in one row without the jitter of anonymous object. You can create a DTO object too. Using Entity-EntityDto mappings with AutoMapper is an easy job.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM