Specified method is not supported - Extension Method

Specified method is not supported - Extension Method

Postby Nahmis » Tue 15 Jun 2010 18:31

We have a short extension method used that breaks when used in a subquery, first off here's the method:
Code: Select all
      public static IQueryable Current(this IQueryable source)
      {
         var entParam = Expression.Parameter(typeof(TSource), "ent");
         var entParam2 = Expression.Parameter(typeof(TSource), "ent");
         return source
            .Where(
               Expression.Lambda>(
                  Expression.Equal(Expression.Property(entParam, typeof(TSource).GetProperty("EntityId")),
                                                       Expression.Constant(0L)), new[] { entParam }))
            .Where(
               Expression.Lambda>(
                  Expression.Equal(Expression.Property(entParam2, typeof(TSource).GetProperty("RecordStatus")),
                                                       Expression.Constant(0L)), new[] { entParam2 }));
      }


It's just a short way for us to filter out older/deleted records since it's done quite often, but there's an issue. For example, this works:

Code: Select all
var contacts = from c in DB.Contacts.Current()
               where !(from u in DB.Users
                    select u.ContactId).Contains(c.Id)
               select c.Id;


However using our .Current() extension method inside that subquery doesn't, like this:

Code: Select all
var contacts = from c in DB.Contacts.Current()
               where !(from u in DB.Users.Current()
                    select u.ContactId).Contains(c.Id)
               select c.Id;


This results in:

Specified method is not supported.
at Devart.Data.Linq.Provider.Query.x.a(SqlNode A_0)
at Devart.Data.Linq.Provider.Query.x.d(Expression A_0, Expression A_1)
at Devart.Data.Linq.Provider.Query.x.b(MethodCallExpression A_0)
at Devart.Data.Linq.Provider.Query.x.j(Expression A_0)
at Devart.Data.Linq.Provider.Query.x.j(Expression A_0, Expression A_1)
at Devart.Data.Linq.Provider.Query.x.b(MethodCallExpression A_0)
at Devart.Data.Linq.Provider.Query.x.j(Expression A_0)
at Devart.Data.Linq.Provider.Query.x.a(UnaryExpression A_0)
at Devart.Data.Linq.Provider.Query.x.j(Expression A_0)
at Devart.Data.Linq.Provider.Query.x.a(Expression A_0, LambdaExpression A_1)
at Devart.Data.Linq.Provider.Query.x.b(MethodCallExpression A_0)
at Devart.Data.Linq.Provider.Query.x.j(Expression A_0)
at Devart.Data.Linq.Provider.Query.x.d(Expression A_0, Expression A_1)
at Devart.Data.Linq.Provider.Query.x.b(MethodCallExpression A_0)
at Devart.Data.Linq.Provider.Query.x.j(Expression A_0)
at Devart.Data.Linq.Provider.Query.x.i(Expression A_0)
at Devart.Data.Linq.Provider.DataProvider.Devart.Data.Linq.Provider.IProvider.GetCommand(Expression query)
at Devart.Data.Linq.DataContext.GetCommand(IQueryable query)


It seems that this should work both places since it's expression based. These two should be equivalent:

Code: Select all
var contacts = from c in DB.Contacts.Current()
               where !(from u in DB.Users.Current()
                    select u.ContactId).Contains(c.Id)
               select c.Id;

Code: Select all
var contacts = from c in DB.Contacts.Current()
               where !(from u in DB.Users
                       where u.EntityId == 0 && e.RecordStatus == 0
                    select u.ContactId).Contains(c.Id)
               select c.Id;


The second does work of course, and generates the following:

Code: Select all
SELECT t1.ID
FROM CONTACT t1
WHERE (NOT (EXISTS
    (
        SELECT t2.CONTACT_ID AS "ContactId"
        FROM USERS t2
        WHERE (t2.CONTACT_ID = t1.ID) AND (t2.ENTITY_ID = :p0) AND (t2.RECORD_STATUS = :p1)
        )
    )) AND (t1.RECORD_STATUS = :p2) AND (t1.ENTITY_ID = :p3)


Is the problem with my expressions, or a bug inside dotConnect not translating it correctly? This would eliminate a lot of extra code every time we have a subquery, any insight/solution would be much appreciated. Thanks!
Nahmis
 
Posts: 30
Joined: Mon 13 Jul 2009 21:38

Postby AndreyR » Tue 22 Jun 2010 12:00

The problem is associated with the fact that LINQ engine performs an attempt to use the name of this method in the generated SQL instead of the result of its execution.
The solution is to build the query manually. Here is a simplified example:
Code: Select all
.Where(
ent => (ent.DEPTNO = 0)
)
.Where(   
   c => Not(
      value(context).EMPs
         .Current()
         .Select(u => u.DEPTNO)
         .Contains(Convert(c.DEPTNO))
      )
   )
.Select(c => c.DEPTNO)
AndreyR
Devart Team
 
Posts: 2919
Joined: Mon 07 Jul 2008 13:16

Postby bmarotta » Mon 21 Feb 2011 13:26

Hi,

would it be possible to extend this error message to output the method which caused the problem?

In the example:

Specified method "Current" is not supported.

It will make easier for the developers to Identify where the error is.

Thanks,
bmarotta
 
Posts: 34
Joined: Wed 29 Sep 2010 11:27

Postby StanislavK » Tue 22 Feb 2011 12:27

Thank you for your suggestion, we will consider such possibility and post here when new information is available.
StanislavK
Devart Team
 
Posts: 1710
Joined: Thu 03 Dec 2009 10:48

Postby StanislavK » Fri 11 Mar 2011 17:58

We've implemented specifying the name of the method that is not supported. This concerns common cases when NotSupportedException is thrown, like the case described by Nahmis. It is not guaranteed though that the method name will be returned in any situation.

This change is available in the new 6.10.121 build of dotConnect for Oracle. The new build can be downloaded from
http://www.devart.com/dotconnect/oracle/download.html
(the trial version) or from Registered Users' Area (for users with active subscription only):
http://secure.devart.com/

For the detailed information about the fixes and improvements available in dotConnect for Oracle 6.10.121, please refer to
http://www.devart.com/forums/viewtopic.php?t=20472
StanislavK
Devart Team
 
Posts: 1710
Joined: Thu 03 Dec 2009 10:48


Return to dotConnect for Oracle