The new version of C# is there, with the useful new feature Tuple Types:
public IQueryable<T> Query<T>(); public (int id, string name) GetSomeInfo() { var obj = Query<SomeType>() .Select(o => new { id = o.Id, name = o.Name, }) .First(); return (id: obj.id, name: obj.name); }
Is there a way to convert my anonymous type object obj to the tuple that I want to return without mapping property by property (assuming that the names of the properties match)?
The context is in a ORM, my SomeType object has a lot of other properties and it is mapped to a table with lot of columns. I wanna do a query that brings just ID and NAME, so I need to convert the anonymous type into a tuple, or I need that an ORM Linq Provider know how to understand a tuple and put the properties related columns in the SQL select clause.
Right-click and choose Refactor | Replace Anonymous Type with Named Class from the context menu. Choose ReSharper | Refactor | Convert | Anonymous to Named Type… from the main menu.
Use anonymous types with LINQThe Select clause in LINQ creates and returns an anonymous type as a result. The following code snippet illustrates this.
Anonymous types in C# are the types which do not have a name or you can say the creation of new types without defining them. It is introduced in C# 3.0. It is a temporary data type which is inferred based on the data that you insert in an object initializer.
The ValueTuple types are mutable, whereas Tuple are read-only. Anonymous types can be used in expression trees, while tuples cannot.
The short answer is no, in the current form of C#7 there is no in-framework way to accomplish your goals verbatim, since you want to accomplish:
Because Query<SomeType>
exposes an IQueryable
, any sort of projection must be made to an expression tree .Select(x => new {})
.
There is an open roslyn issue for adding this support, but it doesn't exist yet.
As a result, until this support is added, you can either manually map from an anonymous type to a tuple, or return the entire record and map the result to a tuple directly to avoid two mappings, but this is obviously inefficient.
While this restriction is currently baked into Linq-to-Entities due to a lack of support and the inability to use parametered constructors in a .Select()
projection, both Linq-to-NHibernate and Linq-to-Sql allow for a hack in the form of creating a new System.Tuple
in the .Select()
projection, and then returning a ValueTuple with the .ToValueTuple() extension method:
public IQueryable<T> Query<T>(); public (int id, string name) GetSomeInfo() { var obj = Query<SomeType>() .Select(o => new System.Tuple<int, string>(o.Id, o.Name)) .First(); return obj.ToValueTuple(); }
Since System.Tuple can be mapped to an expression, you can return a subset of data from your table and allow the framework to handle mapping to your C#7 tuple. You can then deconstruct the arguments with any naming convention you choose:
(int id, string customName) info = GetSomeInfo(); Console.Write(info.customName);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With