【问题标题】:Convert string to decimal in group join linq query在组加入 linq 查询中将字符串转换为十进制
【发布时间】:2012-08-31 13:10:06
【问题描述】:

我必须连接两个表,但只返回第二个表中与第一个表中的记录关联的所有记录的“值”总和相同的那些记录。

from p in db.TPs
join n in db.TNs
on p.Key equals n.Key
where (decimal.Parse(p.Value) == db.TNs.Where( nn => nn.Key == p.Key )
                                       .Sum( nn=> decimal.Parse(kk.Value)))

我正在使用实体框架代码优先。

当然,Linq 抱怨

LINQ to Entities 无法识别方法 'System.Decimal Parse(System.String)' 方法

表很大,我必须减少输出,所以在客户端进行这种转换是不可能的。列类型转换也不是一种选择。

SQL 查询是:

select * from TP as p
join * from TN as n on n.Key = p.Key
where p.Value = (select sum(cast(n.Value as decimal(12,2))) from TN where Key = p.Key)

【问题讨论】:

  • 你试过用Convert.ToDecimal代替decimal.Parse吗?
  • @YograjGupta - 为什么会有帮助? SQL Server 也不知道Convert
  • 因为当你使用 Convert.ToDecimal 时它会生成类似 CONVERT(Decimal(29,4),[t0].[value]) 的 sql,所以试试这个。
  • 也许这个答案会有所帮助:Convert string to int in EF 4
  • @majkinetor,它正在工作,为了测试我使用这个 linq from x in db.TestStringToDecimals select new { x.Id, val= Convert.ToDecimal(x.Value)} 它正在为我生成 sql SELECT [t0].[id] AS [Id], CONVERT(Decimal(29,4),[t0].[value]) AS [val] FROM [TestStringToDecimal] AS [t0]

标签: c# sql linq entity-framework


【解决方案1】:

您可以通过创建一些模型定义的函数来做到这一点。见此链接:Creating and Calling Model-Defined Functions in at least Entity Framework 4

具体来说,要添加一些函数将字符串转换为十进制和字符串转换为int,请按照以下步骤操作:

以 XML 格式打开您的 .EDMX 文件,以便编辑文本。

将您的自定义转换函数添加到“CSDL 内容”部分的“方案”部分

<edmx:ConceptualModels>
<Schema....>

新功能:

<Function Name="ConvertToInt32" ReturnType="Edm.Int32">
  <Parameter Name="myStr" Type="Edm.String" />
  <DefiningExpression>
    CAST(myStr AS Edm.Int32)
  </DefiningExpression>
</Function>
<Function Name="ConvertToDecimal" ReturnType="Edm.Decimal">
  <Parameter Name="myStr" Type="Edm.String" />
  <DefiningExpression>
    CAST(myStr AS Edm.Decimal(12, 2))
  </DefiningExpression>
</Function>

(修改上述 Edm.Decimal 的精度以满足您的需要。)

然后,在您的 c# 代码中,您需要创建相应的静态方法,您可以将其存储在静态类中:

// NOTE: Change the "EFTestDBModel" namespace to the name of your model
[System.Data.Objects.DataClasses.EdmFunction("EFTestDBModel", "ConvertToInt32")]
public static int ConvertToInt32(string myStr)
{
    throw new NotSupportedException("Direct calls are not supported.");
}

// NOTE: Change the "EFTestDBModel" namespace to the name of your model
[System.Data.Objects.DataClasses.EdmFunction("EFTestDBModel", "ConvertToDecimal")]
public static decimal ConvertToDecimal(string myStr)
{
    throw new NotSupportedException("Direct calls are not supported.");
}

最后,调用你的新方法:

using (var ctx = new EFTestDBEntities())
{
    var results = from x in ctx.MyTables
                  let TheTotal = ctx.MyTables.Sum(y => ConvertToDecimal(y.Price))
                  select new
                  {
                      ID = x.ID,
                      // the following three values are stored as strings in DB
                      Price = ConvertToDecimal(x.Price),
                      Quantity = ConvertToInt32(x.Quantity),
                      Amount = x.Amount,
                      TheTotal
                  };
}

您的具体示例如下所示:

from p in db.TPs
join n in db.TNs
on p.Key equals n.Key
where (ConvertToDecimal(p.Value) == 
        db.TNs.Where( nn => nn.Key == p.Key ).Sum( nn=> ConvertToDecimal(kk.Value)))

【讨论】:

  • @majkinetor,如果您使用 Code First,为什么不首先在您的代码第一类中将数据库字段生成为小数?
  • 它现有的数据库。你的意思是如果我还是设置了,code first 会自动转换?
  • @majkinetor,我不这么认为。我不太熟悉使用现有数据库在 Code First 中使用 EF,但您可能想查看 Entity Framework Power Tools 以了解是否有一些东西可以让您更轻松。
  • 我不知道为什么EF团队还没有在框架中实现这个,解决方案就这么简单。感谢您的代码。
【解决方案2】:

很遗憾,LINQ to SQL 无法创建带有字符串到十进制转换的 SQL 表达式。

如果您想这样做,您必须使用以下命令执行您自己的查询:

ExecuteStoredQuery

【讨论】:

  • 嗯...一些框架...这里的问题是失去了便利。我正在创建匿名结果,而 ExecuteStoredQuery 需要类型
【解决方案3】:

您可以将decimal 转换为string,而不是将string 转换为decimal。如果其他方法不这样做,这种方法可能会奏效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-22
    • 2023-03-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多