Specified method is not supported - Extension Method

Discussion of open issues, suggestions and bugs regarding ADO.NET provider for Oracle
Post Reply
Nahmis
Posts: 30
Joined: Mon 13 Jul 2009 21:38

Specified method is not supported - Extension Method

Post by 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!

AndreyR
Devart Team
Posts: 2919
Joined: Mon 07 Jul 2008 13:16

Post by 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)

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

Post by 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,

StanislavK
Devart Team
Posts: 1710
Joined: Thu 03 Dec 2009 10:48

Post by 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

Post by 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

Post Reply