2

I've got a table that looks like this:

Foo
 FooId : int (PK)
 BarId : int
 Baz   : bit
 etc.

It has other columns in it (etc.), but I have a specific query that I want to run that projects some statistics. The query in SQL would look like this:

SELECT 
 BarId, 
 SUM(CAST(Baz AS INT)) AS BazCount
 FROM Foo GROUP BY BarId;

So, I created a Presentation Model class to hold the data, so I can return it to the client.

public partial class FooStatistics
{
  public int BarId { get; set; }
  public int BazCount { get; set; }
}

I'm not 100% sure how to do the same query in LINQ and project it into this object, but I gave it a shot like this:

FooStatistics stats = (
    from f in ctx.Foo
    where <clauses here>
    group f by f.BarId
      into StatsGroup
      select new FooStatistics() {
        BarId = StatsGroup.Key,
        BazCount = StatsGroup.Sum(f => Int32.Parse(f.Baz.ToString()))
      }
    ).FirstOrDefault();

This blows up with the error:

LINQ to Entities does not recognize the method 'Int32 Parse(System.String)' method, and this method cannot be translated into a store expression.

So, I followed the advice given here:

LINQ to Entities does not recognize the method 'Double Parse(System.String)' method, and this method cannot be translated into a store expression

I added this to my .edmx XML

<Function Name="ParseInt" ReturnType="Edm.Int32">
  <Parameter Name="value" Type="Edm.String" />
  <DefiningExpression>
     cast(value as Edm.Int32)
  </DefiningExpression>
</Function>

Then I added a partial class to define the method:

public partial class MyEntities
{
   [EdmFunction("MyEntities", "ParseInt")]
   public static Int32 ParseInt(string value)
   {
       return Int32.Parse(value);
   }
}

And I changed my LINQ to:

FooStatistics stats = (
    from f in ctx.Foo
    where <clauses here>
    group f by f.BarId
      into StatsGroup
      select new FooStatistics() {
        BarId = StatsGroup.Key,
        BazCount = StatsGroup.Sum(f => MyEntities.ParseInt(f.Baz.ToString()))
      }
    ).FirstOrDefault();

But this blows up with:

LINQ to Entities does not recognize the method 'System.String ToString()' method, and this method cannot be translated into a store expression.

So, I changed the function in the .edmx XML to this:

<Function Name="BoolToInt32" ReturnType="Edm.Int32">
   <Parameter Name="value" Type="Edm.Boolean" />
   <DefiningExpression>
      cast(value as Edm.Int32)
   </DefiningExpression>
</Function>

And I changed my static ParseInt to BoolToInt32 accordingly and I changed the LINQ to use that function, but now it blows up with:

The specified method 'Int32 BoolToInt32(Boolean)' cannot be translated into a LINQ to Entities store expression.

Am I close, or am I doing it totally wrong...?

Thanks in advance

Community
  • 1
  • 1
zenocon
  • 1,597
  • 1
  • 17
  • 24

1 Answers1

2

If Baz is a bit, you could add a where and then just use Count() as below

FooStatistics stats = (
    from f in ctx.Foo
    where <clauses here>
       and f.Baz
    group f by f.BarId
      into StatsGroup
      select new FooStatistics() {
        BarId = StatsGroup.Key,
        BazCount = StatsGroup.Count()
      }
    ).FirstOrDefault();
Steven
  • 3,878
  • 3
  • 21
  • 21
  • Thanks @Steven, this works perfectly -- not sure why I overlooked Count -- it was a long day :) – zenocon Oct 14 '11 at 10:24