none
Cross Join in LINQ to Entities

    Question

  • Is it possible to do a cross join in LINQ to Entities?  I'm doing something like this:

     

    from pt in ctx.ProjectTeams.Where(o => o.ProjectTeamId == ProjectTeamId)

    from tym in ctx.TimeYearMonths.Where(o => o.YearId == Year)

    select ....

     

    But I get the following error:

     

    "Unable to create a constant value of type 'Closure type'. Only primitive types ('such as Int32, String, and Guid') are supported in this context."

     

    I'm suspecting it's because I'm doing a cross join?

     

    -Larry

     

    Thursday, August 28, 2008 3:49 PM

Answers

  • Unsigned int (16 or 32) can't be use in a LINQ To Entities query.

    Use

    Int16 yearId16 = 2008;

    instead of

    UInt16 yearId16 = 2008;

    Thursday, August 28, 2008 7:18 PM
  • o.YearId == (Int32)yearId16 does not work (same error). Strange.
    o.YearId == Convert.ToInt32(yearId16) does not work (same error). Strange but expected if (Int32) cast did not work.


    I would assume that is because LINQ queries are translated into expression trees by the C# compiler, and are not evaluated directly. Ultimately, you will end up with something like yearId16.Cast<Int32>() in the expresion tree, but unsigned types are not CLR safe, and seems they can't be used with LINQ to Entities.
    Thursday, August 28, 2008 7:42 PM

All replies

  • I am not sure how mixing .Where in with a syntactic LINQ to Entities query affects the expression. Have you tried this:


    from pt in ctx.ProjectTeams
    where pt.ProjectTeamId == ProjectTeamId
    from tym in ctx.TimeYearMonths
    where tym.YearId == Year
    select ...

    It might produce the same results...but I've seen some odd differences when using the dot notation vs. syntactic LINQ.

    Thursday, August 28, 2008 5:38 PM
  • Lawrence, can you post all your query please.

     

    EF allows cross join.
    Thursday, August 28, 2008 5:52 PM
  • OK, I tested out some other basic cross-joins with my model and it works fine (including combining method syntax with query comprehension syntax.  That's good.

     

    The problem seems to be the variable types used in the query.  Look at the following code, especially in red:

     

    Code Snippet

    Int32 projectTeamId = 1;

    UInt16 yearId16 = 2008;

    Int32 yearId32 = (Int32)yearId16;

     

    var q =

    from pt in ctx.ProjectTeams.Where(o => o.ProjectTeamId == projectTeamId)

    from tym in ctx.TimeYearMonths.Where(o => o.YearId == yearId16)

    select new FactProjectTeamMonthEntity

    {

    ProjectTeamId = pt.ProjectTeamId

    ... etc. ...

    };

     

     

    o.YearId == yearId16 does not work -- it gives the aforementioned error:

     

    "Unable to create a constant value of type 'Closure type'. Only primitive types ('such as Int32, String, and Guid') are supported in this context."

     

    Not sure why it says this because UInt16 is a primitive type.

     

    o.YearId == yearId32 works fine.

     

    o.YearId == (Int32)yearId16 does not work (same error).  Strange.

     

    o.YearId == Convert.ToInt32(yearId16) does not work (same error).  Strange but expected if (Int32) cast did not work.

     

    Taking the cross-join out of the picture (since that is not the problem):

     

    Code Snippet

    var q =

    from tym in ctx.TimeYearMonths

    where tym.YearId == yearId16

    select tym;

     

     

    This gives the same error.  TimeYearMonths.YearId is indeed an Int32 in the model, so I guess I should be using an Int32 for all comparisons.  But it seems that LINQ to Entities should be more forgiving if I compare with another int type (especially if the storage is smaller), and should support inline casting / conversion.

     

    Can someone please confirm if this is a bug?  Or maybe a different philosophy with LINQ to SQL (which handles the casting correctly).

     

    Thanks.

    -Larry

    Thursday, August 28, 2008 6:47 PM
  • Unsigned int (16 or 32) can't be use in a LINQ To Entities query.

    Use

    Int16 yearId16 = 2008;

    instead of

    UInt16 yearId16 = 2008;

    Thursday, August 28, 2008 7:18 PM
  • o.YearId == (Int32)yearId16 does not work (same error). Strange.
    o.YearId == Convert.ToInt32(yearId16) does not work (same error). Strange but expected if (Int32) cast did not work.


    I would assume that is because LINQ queries are translated into expression trees by the C# compiler, and are not evaluated directly. Ultimately, you will end up with something like yearId16.Cast<Int32>() in the expresion tree, but unsigned types are not CLR safe, and seems they can't be used with LINQ to Entities.
    Thursday, August 28, 2008 7:42 PM