es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Cómo asignar el resultado de SQL a una clase que tenga un constructor con parámetros (interfaz)?

¿Alguien sabe cómo puedo asignar los resultados de la consulta SQL a una clase, si la clase tiene un constructor con parámetros y esos parámetros son interfaces con otras clases como claves? (Estoy tratando de reescribir el código EF6 en SQL sin procesar).

Esta es la clase a la que necesito asignar los resultados de la consulta de SQL:

public class DiagSoftDownload
{
    public DiagSoftDownload(IGrouping<diagsoft, logdownload=""> data)
    {
        Name = data.Key.DiagSoftMark.Name;
        Version = data.Key.Version;
        Count = data.Count();
    }
    public string Name { get; set; }
    public string Version { get; set; }
    public int Count { get; set; }
}

Estoy usando SqlDataReaderMapper (también he intentado con dapper) pero muestra un error al asignar, algo como “no se puede asignar a una clase con constructor”.

También estoy pensando en asignar manualmente la clase de destino en el bucle de DataReader y establecer los campos. Pero la consulta de SQL devuelve algunas tablas unidas y mientras Entity Framework 6 puede transformarla a través del método GroupBy usando la clase como clave para la clase DiagSoftDownload necesaria, no entiendo cómo transformar el resultado a la interfaz IGrouping<DiagSoft, LogDownload> manualmente.

Aquí está la consulta de SQL que obtengo de EF6 y ejecuto para obtener el resultado:

SELECT [m].[LogDownloadId], [m].[Date], [m].[DiagSoftId], [m].[MemberShipId], [m.DiagSoft].[DiagSoftId], [m.DiagSoft].[CountNumbersMajor], [m.DiagSoft].[CountNumbersMinor], [m.DiagSoft].[CountNumbersPatch], [m.DiagSoft].[DiagSoftMarkId], [m.DiagSoft].[FileNameGuid], [m.DiagSoft].[VersionMajor], [m.DiagSoft].[VersionMinor], [m.DiagSoft].[VersionPatch], [m.DiagSoft.DiagSoftMark].[DiagSoftMarkId], [m.DiagSoft.DiagSoftMark].[HeavyDuty], [m.DiagSoft.DiagSoftMark].[LanId], [m.DiagSoft.DiagSoftMark].[Name], [m.DiagSoft.DiagSoftMark].[OIN], [m.DiagSoft.DiagSoftMark].[SoftApplicableArea], [m.DiagSoft.DiagSoftMark].[SoftPackageID], [m.DiagSoft.DiagSoftMark].[SoftType]
FROM [LogDownloads] AS [m]
INNER JOIN [DiagSofts] AS [m.DiagSoft] ON [m].[DiagSoftId] = [m.DiagSoft].[DiagSoftId]
INNER JOIN [DiagSoftMarks] AS [m.DiagSoft.DiagSoftMark] ON [m.DiagSoft].[DiagSoftMarkId] = [m.DiagSoft.DiagSoftMark].[DiagSoftMarkId]
WHERE [m].[MemberShipId] = 447
ORDER BY[m.DiagSoft].[DiagSoftId]

Aquí está el código EF6 que estoy tratando de reescribir en SQL sin procesar y que funciona:

IQueryable<diagsoftdownload> query =
    GetDbContext.LogDownloads.Include(m => m.DiagSoft.DiagSoftMark)
    .Where(m => m.MemberShipId == VM.SelectedMembershipLog.MembershipId)
    .GroupBy(m => m.DiagSoft)
.Select(m => new DiagSoftDownload(m));

IOrderedQueryable<diagsoftdownload> ordered_query = query.AsQueryable()
    .OrderByDescending(m => m.Count).ThenBy(m => m.Name).ThenBy(m => m.Version);

Estaría agradecido de cualquier consejo.</diagsoft,>

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Para mapear los resultados de una consulta SQL a una clase con un constructor que tiene parámetros, se puede utilizar un mapper personalizado. Si estás usando SqlDataReaderMapper, puedes crear un mapper personalizado implementando la interfaz IDataReaderMapper. Aquí tienes un ejemplo de cómo podría ser tu mapper personalizado:

    public class DiagSoftDownloadMapper : IDataReaderMapper<diagsoftdownload>
    {
        public DiagSoftDownload Map(IDataReader reader)
        {
            // Obtener los datos del reader
            string name = reader.GetString(reader.GetOrdinal("Name"));
            string version = reader.GetString(reader.GetOrdinal("Version"));
            int count = reader.GetInt32(reader.GetOrdinal("Count"));
    
            // Obtener los objetos de DiagSoft y LogDownload
            var diagSoft = Mapper.Map<diagsoft>(reader);
            var logDownload = Mapper.Map<logdownload>(reader);
    
            // Crear el IGrouping usando los objetos de DiagSoft y LogDownload
            var grouping = new GroupedSequence<diagsoft, logdownload="">(diagSoft, logDownload);
    
            // Devolver el objeto DiagSoftDownload construido a partir del grouping
            return new DiagSoftDownload(grouping);
        }
    }
    

    En el mapper, primero se extraen los valores necesarios del objeto reader. Luego, se utiliza AutoMapper para mapear los objetos DiagSoft y LogDownload desde el reader.

    Por último, se crea un objeto GroupedSequence usando los objetos DiagSoft y LogDownload, y se lo pasa al constructor de DiagSoftDownload. A continuación, se puede utilizar este mapper personalizado en el código:

    // Crear una instancia del mapper personalizado
    var diagSoftDownloadMapper = new DiagSoftDownloadMapper();
    
    // Ejecutar la consulta SQL
    var sqlCommand = new SqlCommand(sqlCommandText, sqlConnection);
    var reader = sqlCommand.ExecuteReader();
    
    // Mapear los resultados de la consulta a una lista de objetos DiagSoftDownload
    var diagSoftDownloads = reader.MapToList(diagSoftDownloadMapper);
    

    En este ejemplo, primero se crea una instancia del mapper personalizado. Luego, se ejecuta la consulta SQL y se mapean los resultados a una lista de objetos DiagSoftDownload utilizando el método de extensión MapToList() de SqlDataReaderMapper.

    Esto debería darte una idea de cómo mapear los resultados de una consulta SQL a una clase con un constructor que toma una interfaz con otras clases como claves.</diagsoft,>

Comments are closed.