那里是C#的新版本,具有有用的新功能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);
}
有没有一种方法可以将我的匿名类型对象obj转换为要返回的元组,而无需按属性映射属性(假定属性名称匹配)?
上下文位于ORM中,我的SomeType对象具有许多其他属性,并且映射到具有很多列的表。我想执行一个仅带ID和NAME的查询,所以我需要将匿名类型转换为元组,或者我需要ORM Linq提供程序知道如何理解元组并将与属性相关的列放在SQL select子句中。
请您参考如下方法:
简短的答案是没有。在C#7的当前形式中,没有框架内的方法可以完全实现目标,因为您想实现以下目标:
由于
Query<SomeType>
公开了
IQueryable
,因此必须对表达式树
.Select(x => new {})
进行任何类型的投影。
有一个 open roslyn issue用于添加此支持,但尚不存在。
结果,在添加此支持之前,您可以手动将匿名类型映射到元组,或者返回整个记录并将结果直接映射到元组,以避免两次映射,但这显然效率低下。
尽管由于缺乏支持以及无法在
.Select()
投影中使用参数化构造函数而使此限制目前流入Linq-to-Entities,但是Linq-to-NHibernate和Linq-to-Sql都允许以在
System.Tuple
投影中创建一个新的
.Select()
,然后使用
.ToValueTuple()扩展方法返回ValueTuple:
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();
}
由于System.Tuple可以映射到表达式,因此您可以从表中返回数据的子集,并允许框架处理到C#7元组的映射。然后,您可以使用选择的任何命名约定来解构参数:
(int id, string customName) info = GetSomeInfo();
Console.Write(info.customName);