使用F#SqlDataConnection,Linq to Sql时出错,'不支持返回自引用常量表达式的IQueryable'

时间:2017-05-18 17:27:26

标签: f# type-providers f#-data

我正在撰写一份注定要成为Azure功能的销售报告。使用FSharp.Data.TypeProviders.SqlDataConnection进行数据访问我在尝试解析产品的父部门时获得System.NotSupportedException: An IQueryable that returns a self-referencing Constant expression is not supported.

脚本看起来像这样:

#r "System.Data.dll"
#r "FSharp.Data.TypeProviders.dll"
#r "System.Data.Entity.dll"
#r "System.Data.Linq.dll"

open System
open Microsoft.FSharp.Data
open Microsoft.FSharp.Data.TypeProviders
open System.Linq
open System.Data.Linq
open System.Data.Entity

type DbConn = SqlDataConnection< @"super secrete connection string here">

type SubSelOut = { ``Department Name``: String;
                   ``Parent Id``: Nullable<int>;
                   ``Product Id``: int }

[< CLIMutable >]
type QueryGrouping = {``Product Id``: Nullable<int>;
                       ``Product SKU``: string;
                       Price: Decimal;
                       ``Department Name``: string;
                       ``Parent Department Name``: string; }

type SkuOut = { sku: string;
                ``Product ID``: Nullable<int>;
                ``Product Name``: string;
                Category: string;
                ``Sub-Category``: string; }

let db = DbConn.GetDataContext()

let p2dQuery = 
    query { for p in db.Products do
            groupJoin p2d in db.Prods_to_depts
              on ( p.Id = p2d.Product_id.Value ) into pd
            groupJoin dep in db.Departments 
              on ( pd.Select(fun e -> e.Dept_id.Value).FirstOrDefault() = dep.Id ) into d
            where ( pd.FirstOrDefault().Is_main )
            select ( { ``Department Name`` = d.Select( fun e -> e.Name).First(); 
                       ``Parent Id`` = d.Max( fun e -> e.Parent_id );
                       ``Product Id`` = p.Id }) } 

query { for oi in db.Order_items do
        join prod in db.Products 
          on ( oi.Product_id.Value = prod.Product_id )
        join pdt in p2dQuery
          on ( prod.Product_id = pdt.``Product Id`` )
        join pd in db.Departments 
          on ( pdt.``Parent Id``.Value = pd.Id ) 
        groupBy ( { ``Product Id`` = oi.Product_id;
                    ``Product SKU`` = oi.Product_sku;
                    Price = prod.Price;
                    ``Department Name`` = pdt.``Department Name``;
                    ``Parent Department Name`` = pd.Name; } ) into gt  
        select ( { sku = gt.Key.``Product SKU``;
                   ``Product ID`` = gt.Key.``Product Id``;
                   ``Product Name``  = gt.Select( fun (oi,_,_,_) -> oi.Product_name ).FirstOrDefault();
                   Category = gt.Select(  fun (_,_,_,pd) -> pd.Name ).FirstOrDefault();
                   ``Sub-Category`` = gt.Select( fun (_,_,d,_) -> d.``Department Name`` ).FirstOrDefault(); } ) }
|> Seq.toList

可以用以下方法复制相关的数据结构:

CREATE TABLE [dbo].[products](
       [id] [int] IDENTITY(1000,1) NOT NULL PRIMARY KEY,
       [sku] [nvarchar](300) NULL,
       [name] [nvarchar](500) NULL,
       [price] [decimal] NOT NULL 
       --additional product props
       );

CREATE TABLE [dbo].[departments](
       [id] [int] IDENTITY(1000,1) NOT NULL PRIMARY KEY,
       [name] [varchar](200) NULL,
       [parent_id] [int] NULL
       --additional department props
       );

CREATE TABLE [dbo].[products_to_deptartments](
       [id] [int] IDENTITY(10000,1) NOT NULL PRIMARY KEY,
       [department_id] [int] NULL, 
       [product_id] [int] NULL,
       [is_main] [bit] NOT NULL ); 

CREATE TABLE [dbo].[order_items](
       [id] [int] IDENTITY(1000,1) NOT NULL PRIMARY KEY,
       [order_id] [nvarchar](50) NULL,
       [product_id] [int] NULL,
       [product_sku] [nvarchar](50) NULL,
       [product_name] [nvarchar](500) NULL,
       [price] [decimal] NOT NULL,
       [quantity] [int] NOT NULL
       --additional order item info
       );
GO

我尝试克隆的SQL查询是这样的:

SELECT   
  --agragate data here
  department_table.department_name,
  parent_department.department_name AS parent_name
FROM order_items
LEFT OUTER JOIN products 
  ON products.id = order_items.product_id
LEFT OUTER JOIN ( SELECT  
                      MAX(departments.department_name) AS department_name, 
                         MAX(departments.parent_id) AS parent_id,
                      products.id
                    FROM products 
                    INNER JOIN products_to_deptartments 
                         ON products.id = products_to_deptartments.product_id 
                    INNER JOIN departments 
                         ON products_to_deptartments.dept_id = departments.id 
                    WHERE products_to_deptartments.is_main = 1
                    GROUP BY products.id ) AS department_table
  ON products.id = department_table.product_id
LEFT OUTER JOIN departments parent_department 
  ON parent_department.id = department_table.parent_id
GROUP BY
  order_items.id,
  order_items.sku,
  products.price,
  department_table.name,
  parent_department.name 
ORDER BY order_items.product_sku;
GO

0 个答案:

没有答案