Доступ к динамически созданной хранимой процедуре из LINQ

Я поворачиваю данные в хранимой процедуре MS SQL. Сводные столбцы создаются динамически с использованием параметра хранимой процедуры (например: «location1, location2, location3»), поэтому количество столбцов, которые будут сгенерированы, неизвестно. Вывод должен выглядеть так (где местоположения берутся из параметра хранимой процедуры):

время заказа | Местоположение1 | Местоположение2 | Местоположение3

Есть ли шанс, что это можно использовать в LINQ to SQL? Когда я перетащил эту процедуру в файл dbml, она показывает, что эта процедура возвращает тип int.

Столбцы, которые я использую из таблицы log_sales:

  • Местоположение (различное местоположение, которое я поворачиваю),
  • Плата (сумма денег)
  • Время заказа

Хранимая процедура:

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

В файле dbml designer.cs часть кода моей хранимой процедуры:

[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));
}

person GrZeCh    schedule 05.11.2008    source источник


Ответы (3)


Предполагая действительно острую динамическую потребность, вы можете использовать DataContext.ExecuteQuery

Просто придумайте тип, который покроет область результатов (имена свойств должны совпадать с именами столбцов в запросе):

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

Тогда позвони

IEnumerable<DynamicResult> result =
  myDataContext.ExecuteQuery<DynamicResult>(commandString, param1);
person Amy B    schedule 05.11.2008
comment
С другой стороны, я не могу сказать, что это действительно динамическое решение, потому что я должен знать, что будет возвращено. Для меня это работает, потому что у меня около 10-15 локаций, но для тех, у кого их намного больше, это может быть проблематично. - person GrZeCh; 06.11.2008
comment
Если вы хотите работать с типизированными данными во время выполнения, DataSet вполне удовлетворяет эту потребность. Linq(ToData) предназначен для проверки типов во время компиляции. - person Amy B; 06.11.2008
comment
Мне это кажется не очень динамичным, так как он создал статический класс, а затем выполнил команду, которая возвращает ожидаемый тип. Звучит вполне нормально для меня. Динамический больше похож на неизвестное количество столбцов и типов данных, которые генерируются динамически созданной командой SQL. - person Piotr Kula; 29.01.2013
comment
Спрашивающий @ppumkin сказал: вывод должен выглядеть так. Я просто работал в рамках заданного вопроса. - person Amy B; 29.01.2013

Вы можете создать свой объект linq для доступа после возвращенного набора данных.

Но будет ли это действительно полезно. Linq полезен для типовых вызовов, а не для динамических результатов. Вы бы не знали, что искать во время компиляции.

person bovium    schedule 05.11.2008

Вы бы запустили свой оператор выбора

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

и запишите результат в такой тип

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

А затем "развернуть"/организовать это в памяти

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)
       })
     });

Вот второй поворотный Linq, который помещает данные в XML вместо анонимных типов.

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))
     ))
  ));
person Amy B    schedule 05.11.2008