【问题标题】:Accessing dynamically created stored procedure from LINQ从 LINQ 访问动态创建的存储过程
【发布时间】:2010-09-20 23:21:29
【问题描述】:

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

【问题讨论】:

    标签: sql linq stored-procedures pivot


    【解决方案1】:

    假设真正迫切的动态需求,您可以使用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);
    

    【讨论】:

    • 另一方面,我不能说这是真正的动态解决方案,因为我必须知道将返回什么。对我来说这很有效,因为我有大约 10 到 15 个地点,但对于拥有更多地点的人来说,这可能会很麻烦。
    • 如果您想处理运行时类型的数据,DataSet 可以很好地满足这一需求。 Linq(ToData) 是关于编译时类型检查的。
    • 对我来说看起来不是很动态,因为他创建了一个静态类,然后执行了一个返回预期类型的​​命令。对我来说听起来很正常。动态更像是未知数量的列,以及由动态创建的 SQL 命令生成的数据类型。
    • @ppumkin asker 说:“输出应该看起来像”。我只是在所述问题的限制下工作。
    【解决方案2】:

    您可以在返回数据集后创建 linq 对象以供访问。

    但这真的有用吗? Linq 对于类型安全调用而不是动态结果很有用。您将不知道要查找什么编译时间。

    【讨论】:

      【解决方案3】:

      你会运行你的选择语句

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-07-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-18
        • 1970-01-01
        • 1970-01-01
        • 2010-10-18
        相关资源
        最近更新 更多