Pergunta

Eu estou girando dados no procedimento armazenado MS SQL. Colunas que são articuladas são criados dinamicamente usando parâmetro de procedimento armazenado (para exampe: "location1, location2, Location3") para que o número de colunas que será gerado não é conhecido. Saída deve ser semelhante (onde locais são tomadas a partir de parâmetro de procedimento armazenado):

OrderTime | location1 | Location2 | Location3

Qualquer chance de que isso pode ser usado em LINQ to SQL? Quando eu arrastei este procedimento para dbml arquivo mostra que esse procedimento retorna tipo int.

Colunas eu uso da tabela log_sales são:

  • Localização (vários local que eu estou girando),
  • Carga (quantidade de dinheiro)
  • OrderTime

procedimento armazenado:

CREATE PROCEDURE [dbo].[proc_StatsDay] @columns NVARCHAR(64) AS

DECLARE @SQL_PVT1 NVARCHAR(512), @SQL_PVT2 NVARCHAR(512), @SQL_FULL NVARCHAR(4000);

SET @SQL_PVT1 =  'SELECT OrderTime, ' + LEFT(@columns,LEN(@columns)-1) +'
FROM (SELECT ES.Location, CONVERT(varchar(10), ES.OrderTime, 120),ES.Charge
        FROM dbo.log_sales ES
        ) AS D (Location,OrderTime,Charge)
        PIVOT (SUM (D.Charge) FOR D.Location IN
            (';
SET @SQL_PVT2 = ') )AS PVT
ORDER BY OrderTime DESC';

SET @SQL_FULL = @SQL_PVT1 + LEFT(@columns,LEN(@columns)-1) + 
@SQL_PVT2;       

EXEC sp_executesql @SQL_FULL, N'@columns NVARCHAR(64)',@columns = @columns

Em dbml designer.cs arquivar o meu procedimento armazenado parte do código:

[Function(Name="dbo.proc_StatsDay")]
public int proc_EasyDay([Parameter(DbType="NVarChar(64)")] string columns)
{
    IExecuteResult result = this.ExecuteMethodCall(this,((MethodInfo)MethodInfo.GetCurrentMethod())), columns);
    return ((int)(result.ReturnValue));
}
Foi útil?

Solução

Assumindo necessidade dinâmica verdadeiramente terrível, você poderia usar DataContext.ExecuteQuery

Apenas chicotear acima de um tipo que vai cobrir o espaço resultado (os nomes de propriedade devem coincidir com os nomes das colunas na consulta):

public class DynamicResult
{
  public DateTime OrderDate {get;set;}
  public decimal? Location1 {get;set;}
  public decimal? Location2 {get;set;}
//..
  public decimal? Location100 {get;set;}
}

Em seguida, chamar

IEnumerable<DynamicResult> result =
  myDataContext.ExecuteQuery<DynamicResult>(commandString, param1);

Outras dicas

Você pode criar seu objeto linq para acesso após o seu conjunto de dados retornado.

Mas teria que ser realmente de qualquer uso. Linq são úteis para chamadas typesafe e resultados não dinâmicos. Você não sabe o que procurar tempo de compilação.

Você iria executar a sua instrução select

SELECT ES.Location, DateAdd(dd, DateDiff(dd, 0, ES.OrderTime), 0),ES.Charge
FROM dbo.log_sales ES

e captura o resultado para um tipo como este

public class LogSale
{
  public string Location {get;set;}
  public DateTime OrderDate {get;set;}
  public decimal Charge {get;set;}
}

E, em seguida, "pivot" / organizar isso em memória

List<LogSale> source = LoadData();
var pivot = source
  .GroupBy(ls => ls.OrderDate)
  .OrderBy(g => g.Key)
  .Select(g => new {
     Date = g.Key,
     Details = g
       .GroupBy(ls => ls.Location)
       .Select(loc => new {
          Location = loc.Key,
          Amount = loc.Sum(ls => ls.Charge)
       })
     });

Aqui está um segundo pivoty Linq que empurra os dados em XML em vez de tipos anônimos.

var pivot = source
  .GroupBy(ls => ls.OrderDate)
  .OrderBy(g => g.Key)
  .Select(g => new XElement("Date",
    new XAttribute("Value", g.key),
    g.GroupBy(ls => ls.Location)
     .Select(loc => new XElement("Detail",
       new XAttribute("Location", loc.Key),
       new XAttribute("Amount", loc.Sum(ls => ls.Charge))
     ))
  ));
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top