将存储过程PIVOT表转换为LINQ查询

时间:2015-09-15 11:57:46

标签: c# linq stored-procedures asp.net-web-api entity-framework-6

我的想法是转换我之前定义的当前存储过程。目的是,我无法使用存储过程从数据库返回数据。出于此目的的原因是在查询中留下。我需要将现有表转换为数据透视表,然后我必须通过ASP.NET WebAPI返回数据。此数据透视表是动态的,这意味着当用户添加新文章时,它将作为列添加到数据透视表中。

普通表如下所示:

datum      | rate     | article
--------------------------------
2013-01-03 |  97,766..|  DE011
2013-01-05 |  90.214..|  DE090
2013-01-10 |  97,890..|  DE011
2013-01-13 |  65,023..|  DE220
2013-01-13 |  97,012..|  DE300
2013-01-15 |  97,344..|  DE300
....

数据透视表应如下所示:

rate | DE011 | ... | DE090 | ... | DE220 | ... | DE300
-------------------------------------------------------
100  |   0   | ... |   1   | ... |   0   | ... |   0
 98  |   2   | ... |   0   | ... |   1   | ... |   0
 97  |   0   | ... |   0   | ... |   0   | ... |   2
 90  |   0   | ... |   1   | ... |   0   | ... |   4
...

datum对于数据透视表很重要,因为用户必须在角度视图中进行一些输入..在此示例中,用户正在选择dateFromdateTo输入。费率将在数据透视列rate中查看数字的方式。文章描述在新表格列标题中,每个文章的费率将计算在内。

我的存储过程在SQL Server中运行正常。但是,在将SP导入EDM模型后,实体框架定义了一个返回类型INT,这对我来说是不可能的。

这是EF的代码:

 public virtual int getMonthIsin(Nullable<System.DateTime> fromDate, Nullable<System.DateTime> toDate)
        {
            var fromDateParameter = fromDate.HasValue ?
                new ObjectParameter("fromDate", fromDate) :
                new ObjectParameter("fromDate", typeof(System.DateTime));

            var toDateParameter = toDate.HasValue ?
                new ObjectParameter("toDate", toDate) :
                new ObjectParameter("toDate", typeof(System.DateTime));

            return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction("getMonthIsin", fromDateParameter, toDateParameter);
        }

我也在我的WebAPI-Controller中尝试过.SqlQuery(),如下所示:

return db.Database.SqlQuery<IQueryable>("EXEC getMonthIsin @fromDate, @toDate", fromDate, toDate).AsQueryable();

但它没有用。

好吧,现在的想法是尝试LINQ查询并获取返回值。我不知道如何实现这一点:(

目前,我已尝试过大约此LINQ查询:

public IQueryable getDatas(DateTime fromDate, DateTime toDate)
{
   var query = from t in db.table1
               where t.datum >= fromDate && t.datum <= toDate
               group t by t.article
                 into grp
                 select new
                 {
                    articles = grp.Key,
                    rate = grp.Select(g => g.rate),
                    total = grp.Select(g => g.rate).AsQueryable()
                 };

   return query;
}

但这并不是真正的回报。任何人都可以帮助我,这将是非常有帮助的!我会赞成每个好的答案!

1 个答案:

答案 0 :(得分:1)

实体框架不适合获取动态数据结构。 Dapper是此处使用的工具。它基本上是IDbConnection上的一组扩展方法,其中一个是Query,返回IEnumerable<dynamic>,其中dynamic是实现IDictionary<string, object>的对象。获取数据非常简单:

IEnumerable<IDictionary<string, object>> result;

using (var cnn = new SqlConnection(connectionString))
{
    cnn.Open();

    var p = new DynamicParameters();
    p.Add(" @fromDate", fromDate, DbType.DateTime);
    p.Add(" @toDate", toDate, DbType.DateTime);

    result = (IEnumerable<IDictionary<string, object>>)
                cnn.Query(sql: "getMonthIsin", 
                          param: p, 
                          commandType: CommandType.StoredProcedure);
}

现在你有一个IEnumerable<IDictionary<string, object>>,其中一个项目(IDictionary<string, object>)代表存储过程结果集中的一行键/值对:

Key    Value
-----  ----
rate   100
DE011  0
...    ...
DE090  1
...    ...
DE220  0
...    ...
DE300  0

由你决定如何离开这里。例如,您可以将结果转换为DataTable,如下所示:Dictionary<string, object> to DataTable

顺便说一句,Dapper不仅简单,而且速度也非常快。