linq-to-entities tuples anonymous-types linq-to-nhibernate c#-7.0

linq to entities - Convertir el tipo anónimo al nuevo tipo de tupla C#7



linq-to-entities tuples (3)

La respuesta corta es no, en la forma actual de C # 7 no hay una forma en el marco para lograr sus objetivos textualmente, ya que quiere lograr:

  • Linq-a-entidades
  • Mapeo a un subconjunto de columnas
  • Evitar la asignación de propiedades por propiedades de un tipo personalizado o anónimo a una tupla de C # 7 mediante la asignación directa a una tupla de C # 7.

Debido a que la Query<SomeType> expone un IQueryable , cualquier tipo de proyección debe realizarse en un árbol de expresiones .Select(x => new {}) .

Hay un problema abierto de Roslyn para agregar este soporte, pero aún no existe.

Como resultado, hasta que se agregue este soporte, puede mapear manualmente desde un tipo anónimo a una tupla, o devolver el registro completo y asignar el resultado a una tupla directamente para evitar dos asignaciones, pero esto es obviamente ineficaz.

Si bien esta restricción actualmente está incorporada a Linq-to-Entities debido a la falta de soporte y la incapacidad de usar constructores parametrizados en una proyección .Select() , tanto Linq-to-NHibernate como Linq-to-Sql permiten una piratería. la forma de crear un nuevo System.Tuple en la proyección .ToValueTuple() , y luego devolver un ValueTuple con el método de extensión .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(); }

Dado que System.Tuple puede asignarse a una expresión, puede devolver un subconjunto de datos de su tabla y permitir que el marco administre la asignación a su tupla de C # 7. Luego puede deconstruir los argumentos con cualquier convención de nomenclatura que elija:

(int id, string customName) info = GetSomeInfo(); Console.Write(info.customName);

La nueva versión de C # está ahí, con la nueva característica útil 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); }

¿Hay alguna forma de convertir mi objeto de tipo anónimo obj a la tupla que deseo devolver sin asignar la propiedad por propiedad (suponiendo que los nombres de las propiedades coincidan)?

El contexto está en un ORM, mi objeto SomeType tiene muchas otras propiedades y se asigna a una tabla con muchas columnas. Quiero hacer una consulta que traiga solo ID y NOMBRE, por lo que debo convertir el tipo anónimo en una tupla, o necesito que un proveedor de ORM Linq sepa cómo entender una tupla y colocar las columnas relacionadas con las propiedades en la cláusula de selección de SQL.


Por supuesto, creando la tupla de su expresión LINQ:

public (int id, string name) GetSomeInfo() { var obj = Query<SomeType>() .Select(o => (o.Id,o.Name)) .First(); return obj; }

De acuerdo con otra respuesta con respecto a las tuplas pre-C # 7, puedes usar AsEnumerable() para evitar que EF mezcle las cosas. (No tengo mucha experiencia con EF, pero esto debería hacer :)

public (int id, string name) GetSomeInfo() { var obj = Query<SomeType>() .AsEnumerable() .Select(o => (o.Id,o.Name)) .First(); return obj; }


Si bien los literales de tupla no se admiten actualmente en los árboles de expresión, no significa que el tipo ValueTuple no lo sea. Sólo tienes que crearlo explícitamente.

public (int id, string name) GetSomeInfo() => Query<SomeType>() .Select(o => ValueTuple.Create(o.Id, o.Name)) .First();