Преобразование анонимного типа в новый тип кортежа C# 7
новая версия C# есть, с полезными новыми типами кортежей функций:
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 и имя, поэтому мне нужно преобразуйте анонимный тип в кортеж, или мне нужно, чтобы поставщик ORM Linq знал, как понять кортеж и поместить связанные со свойствами столбцы в предложение SQL select.
2 ответов
короткий ответ-нет, в текущей форме C#7 нет способа в рамках для достижения ваших целей дословно, так как вы хотите выполнить:
- Linq-to-entities
- отображение в подмножество столбцов
- избегание свойства путем сопоставления свойств с пользовательским или анонимным типом кортежу C#7 путем сопоставления непосредственно кортежу C#7.
, потому что Query<SomeType>
предоставляет IQueryable
, любой вид проекции необходимо сделать к дерево выражений .Select(x => new {})
.
есть открыть выпуск roslyn для добавления этой поддержки, но она еще не существует.
в результате, пока эта поддержка не будет добавлена, вы можете вручную сопоставить анонимный тип с кортежем или вернуть всю запись и сопоставить результат с кортежем напрямую, чтобы избежать двух сопоставлений, но это явно неэффективно.
в то время как это ограничение в настоящее время запечено в Linq-to-Entities из-за отсутствия поддержка и невозможность использования параметрических конструкторов в A .Select()
проекция, как Linq-to-NHibernate, так и Linq-to-Sql позволяют взломать в виде создания нового System.Tuple
на .Select()
проекция, а затем возврат ValueTuple с .ToValueTuple () метод расширения:
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();
}
Начиная С Системы.Кортеж может быть сопоставлен с выражением, вы можете вернуть подмножество данных из таблицы и позволить структуре обрабатывать сопоставление с кортежем C#7. Вы можете затем деконструируйте аргументы с любым соглашением об именах, которое вы выбираете:
(int id, string customName) info = GetSomeInfo();
Console.Write(info.customName);
конечно, создав кортеж из вашего выражения LINQ:
public (int id, string name) GetSomeInfo() {
var obj = Query<SomeType>()
.Select(o => (o.Id,o.Name))
.First();
return obj;
}
По данным другой ответ Что касается кортежей pre-C# 7, вы можете использовать AsEnumerable()
чтобы предотвратить EF, чтобы смешать вещи. (У меня нет большого опыта работы с EF, но это должно сделать:)
public (int id, string name) GetSomeInfo() {
var obj = Query<SomeType>()
.AsEnumerable()
.Select(o => (o.Id,o.Name))
.First();
return obj;
}