Selecting specific columns using linq: What gets transferred?
You don't need to create new classes to select few columns from a table. You can use anonymous types for that.
var qry = from b in dc.Blobs
orderby b.RowVersion descending
select new { b.Id, b.Size, b.Signature, b.RowVersion};
return qry.ToList();
Only selected columns are transferred. There is no difference between using plain SQL and using LINQ to SQL. When you are executing LINQ query, it is converted to plain SQL and executed. Then result is mapped to your objects.
You can use SQL Server Profiler to see what query was generated and executed on server. Also you can use LINQPad to see what SQL will be generated from your query. In your case query will be same either you use BlobDetails or anonymous object:
SELECT [t0].[Id], [t0].[Size], [t0].[Signature], [t0].[RowVersion]
FROM [Blobs] AS [t0]
ORDER BY [t0].[RowVersion] DESC
Return selected specified columns
If BlobDetails
isn't the LINQ entity, then you can do it directly:
var qry = from b in dc.Blobs
orderby b.RowVersion descending
select new BlobDetails {
Id = b.Id, Size = b.Size,
Signature = b.Signature, RowVersion = b.RowVersion};
return qry.ToList();
However; if BlobDetails
is a LINQ entity, you need to use subtrefuge:
var qry = from b in dc.Blobs
orderby b.RowVersion descending
select new {b.Id, b.Size, b.Signature, b.RowVersion};
var typedQry = from b in qry.AsEnumerable()
select new BlobDetails {
Id = b.Id, Size = b.Size,
Signature = b.Signature, RowVersion = b.RowVersion};
return typedQry.ToList();
The AsEnumerable
breaks the LINQ composition, making it work.
How to Select from table records except some columns
If you don't want to use an anonymous type to specify the fields you want, you can:
- Live with having the ID in the result set, or
- Include all of the columns in the
Select
except for the ID, or - 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
Select all columns on an object with Linq
If you want to avoid anonymous types and get everything, why not just return an IEnumerable
of the original transaction item?
var transactions = from t in db.Transactions
where t.SellingPrice != 0
select t;
Exclude a column from a select using LINQ
Specify each column that you do want in your select statement:
var users = from u in context.Users
where u.UserId == userId
select u.UserId, u.Watever, etc... ;
How to return the result set with columns with Linq
You cannot return an anonymous type from a function, they are strictly "inline" classes. When you return it, the foreach loop will only be able to interpret the result as an plain object. I guess you could use reflection to query the property names and values, however it seems much more straight forward to define a data transfer type to hold the results.
See this question, and this blog post.
So you could create a simple struct or class:
public class MyDataResult
{
public object Column1 { get; set; }
public object Column2 { get; set; }
}
Then modify your query in the function:
public static IQueryable<MyDataResult> GetInfo(MyEntityModel oEntityModel)
{
var query =
(from t in oEntityModel.Table1
from u in t.Table2
where t.Status == true &&
u.Status == true
select new MyDataResult
{
Column1 = t.Column1,
Column2 = u.Column2
})
return query;
}
Something like that should work. Note that I used "object" for the properties in MyDataResult. I don't know the types of the columns you are returning, you should use the actual types in order to get full intellisense.
Related Topics
SQL Scheduling - Select All Rooms Available for Given Date Range
Xml Query() Works, Value() Requires Singleton Found Xdt:Untypedatomic
How to Group by and Return Sum Row in Postgres
Row with Minimum Value of a Column
Select Average from MySQL Table with Limit
Oracle SQL Returns Rows in Arbitrary Fashion When No "Order By" Clause Is Used
Sync Between SQL Server and MySQL Server
How to Retrieve Same Column Twice with Different Conditions in Same Table
SQL Query with Union in Doctrine Symfony
How to Store SQL Server Sort Order in a Variable
Query Records and Group by a Block of Time
Find the Maximum Consecutive Years for Each Id's in a Table(Oracle SQL)
SQL Function to Get Count of How Many Times String Appears in Column
Bigquery: How to Group and Count Rows Within Rolling Timestamp Window
Oracle SQL: the Insert Query with Regexp_Substr Expression Is Very Long ( Split String )