Hux
Hux

Reputation: 3122

LINQ-SQL - Using static readonly fields within CompiledQuery.Compile?

I've encountered a strange issue using CompiledQuery.Compile. When trying to use a static readonly field within a query, I get the following error message:

Class member X is unmapped

If I move the field decleration out of the partial class into another class not related to LINQ-SQL, then I get the following:

Object reference not set to an instance of an object

If I pass the fields through as an argument, then I see no errors and the query works fine and generates the expected SQL.

An example is as below:

partial class Order 
{
    public static readonly string Complete = "Complete";
    public static readonly string Pending = "Pending";

    public static readonly Func<DataContext, Order, bool> IsComplete =
        CompiledQuery.Compile((DataContext context, Order o) =>
           Complete == o.Status);
}

Usage:

var test = from o in db.Orders
           select new
           {
               IsComplete = Order.IsComplete(db, o)
           };

This generates the errors mentioned. If I add a string[] as another argument to the CompiledQuery then I see no errors. Also, If I modify the strings to be const instead of static readonly this works as well, but I imagine that is due to the values being assigned at compile time.

Is there any way of getting the static readonly fields working?

Upvotes: 4

Views: 547

Answers (2)

Bob Vale
Bob Vale

Reputation: 18474

The problem is occuring because Linq-To-Sql is trying to translate your expression into the backend SQL, because the logic sees an unmapped class member it cannot cope with converting it.

I would suggest you create a wrapping property to do the work for you

partial class Order  { 

  public static readonly string Complete = "Complete"; 
  public static readonly string Pending = "Pending"; 

  private static readonly Func<DataContext, Order, bool> _isComplete;

  public static Func<DataContext, Order, bool> IsComplete {
    get {
      if (_isComplete == null) {
        var complete=Complete; 
        _isComplete CompiledQuery.Compile((DataContext context, Order o) => 
                                                       complete == o.Status); 
      }
      return _isComplete;
    }
  }
}

}

Upvotes: 2

Julien Lebosquain
Julien Lebosquain

Reputation: 41243

There is no problem if you're not mixing normal queries and compiled queries. The following works and will give you better performance overall, at the cost of not being able to reuse a simple IsCompleted compiled everywhere you like.

public static readonly Func<YourDataContext, IEnumerable<Order>> GetCompletedOrders =
    CompiledQuery.Compile((YourDataContext context) =>
        context.Orders.Where(o => Complete == o.Status));

Upvotes: 0

Related Questions