LINQ to Entities字符串为双转换

时间:2012-09-10 15:57:23

标签: entity-framework-4

我第一次使用LINQ to Entities。

我的数据存储有一个字符串字段,取决于某些其他字段通常是整数。我无法改变这个数据库的结构。

EF中的表格是masterdatas。

我正在尝试根据基于varname字段的分组在varvalue字段中为这些记录创建总和:

var varsum = from md in context.masterdatas
             where md.imparcid == SelectedDataSet.imparcid && md.varname == t.VarName
             group md by md.varname into g
             select new { varname = g.Key, SummedAmt = g.Sum(md => Convert.ToDouble(md.varvalue)) };

我收到错误LINQ to Entities无法识别方法Double ToDouble(系统字符串)。

基于this SO问题,我在我的EDMX模型中添加了一个DefiningExpression,并在我的datamodel的部分类中定义了该函数并使用了这段代码:

var varsum = from md in context.masterdatas
             where md.imparcid == SelectedDataSet.imparcid && md.varname == t.VarName
             group md by md.varname into g
             select new { varname = g.Key, SummedAmt = g.Sum(md => context.ParseDouble(md.varvalue)) };

现在我收到一个错误,即ParseDouble函数无法转换为LINQ to实体存储表达式。

我真正想做的就是让这个SQL语句运行:

SELECT [varname]
      ,[vartype]
      ,Sum(CASE WHEN Isnumeric([varvalue])=1 THEN cast([varvalue] as float) Else 0 END)
  FROM [masterdata]
  Group by varname, imparcid, vartype
  Having imparcid=25 AND varname = 'S2CMT8B'

我对完成这项工作的最佳方法感到茫然。

1 个答案:

答案 0 :(得分:2)

在LINQ查询的最后一行,您需要在上下文上调用静态 ParseDouble方法,而不是context实例:

// ...
select new { varname = g.Key, SummedAmt = g.Sum(md =>
    MyContextClass.ParseDouble(md.varvalue)) };
//  ^^^^^^^^^^^^^^
//  NOT the context instance, just the class name because ParseDouble is static

我相信只有在这种情况下,EdmFunction属性由EF处理,否则它会尝试像抛出异常的普通.NET方法一样调用该方法。

修改

EdmFunction属性中指定正确的模型名称空间也很重要。如果您的EDMX看起来像这样......

<edmx:ConceptualModels>
  <Schema Namespace="MyDBModel" Alias="Self"
      xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation"
      xmlns="http://schemas.microsoft.com/ado/2008/09/edm">

    <!-- etc. -->

    <Function Name="ParseDouble" ReturnType="Edm.Double">
      <Parameter Name="stringvalue" Type="Edm.String" />
      <DefiningExpression>
        cast(stringvalue as Edm.Double)
      </DefiningExpression>
    </Function>

  </Schema>
</edmx:ConceptualModels>

...您必须指定架构MyDBModel的命名空间作为EdmFunctionAttribute的第一个参数:

[EdmFunction("MyDBModel", "ParseDouble")]
public static double ParseDouble(string stringvalue)
{
    // ...
}

否则ParseDouble将被视为普通的.NET方法,并导致无法将其转换为商店表达式。