none
The mapping of interface member [...] is not supported.

    Question

  • We have tables that have the same members and so we want to access them using the same methods.
    So we created interfaces that the classes created by the DBML file implement and then created generic methods.
    Everything works fine, we can even access each elements of the IQueryable one by one using First() or Skip().First() but the application crashes when we try have a GetEnumerator().
    The exception thrown is "NotSupportedException: The mapping of interface member IMyInterface.value_text is not supported."

    Code Snippet
        // Applied an interface to the class created by the DBML
        public interface IMyInterface { string value_text { get; set; } }
        public partial class tbl_product_value : IMyInterface {};

            // The generic method
            public void foo<T>(System.Data.Linq.Table<T> table) where T : class, IMyInterface
            {
                // The query
                var query = (
                    from var in table
                    where var.value_text == "bar"
                    //where var.value_text.StartsWith( "A" )   // <= Even this works with GetEnumerator() !
                    select var );

                // Accessing each elements one by one
                for( int i=0; i<query.Count(); ++i )
                {
                    var value = query.Skip(i).First();    //    <= This works fine ! (but really slow)
                    Console.Out.WriteLine( value.value_text );
                }

                // Trying to get the GetEnumerator()
                foreach( var value in query )  // <= Fails here with "NotSupportedException: The mapping of interface member IMyInterface.value_text is not supported."
                {
                    Console.Out.WriteLine( value.value_text );
                }
            }

        // The calling statement
        foo<tbl_product_value>( engine.Context.tbl_product_values );


    I don't understand why L2S is unable to map the member value_text since this member HAS the mapping attributes. Even if it is an interface implementation.
    The simple proof of that is that when accessing elements one by one works perfectly.
    But of course, the problem with accessing each entries one by one is really slow since it execute a new SQL query for each rows (plus the .Count())
    Tuesday, April 08, 2008 9:58 AM

Answers

  • Hi,

     

    yes I understand your concerns about .AsEnumerable() (it was my first attempt).

     

    The more important point is that using

    var qry1 = from o in table

    where o.Text.Equals("XYZ")

    select o;

    will work.

    This is translated to

    SELECT [t0].[ID], [t0].[Text], [t0].[Int1]
    FROM [dbo].[TestTable1] AS [t0]
    WHERE [t0].[Text] = @p0
    -- @p0: Input NVarChar (Size = 3; Prec = 0; Scale = 0) [XYZ]
    -- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.21022.8

    and shows the right result.

     

    The funny thing is that 'where o.Text == "XYZ"' is translated to the same Sql statement (you can check this in Debugger) but gives the exeception message.

     

    regards

    Philipp

    Wednesday, April 09, 2008 3:34 PM

All replies

  • Hi,

     

    I guess L2S doesn't allow it to prevent infinite loop. Maybe you call foo<tbl_product_value>(...) and this will create an instance of tbl_product_value which again calls foo<tbl_product_value>....

    I'm not really sure if this is the reason for the message but I suppose it.

     

    What's happen if you make this generic method static. From what I can see the is no link to instance data.

     

    regards

    Philipp

    Wednesday, April 09, 2008 8:04 AM
  • Hello,

     

    To me, you can as well call a non generic method foo that will create an instance of tbl_product_value which then calls foo again. I don't see the link with the generics.

    The only difference is that inside the method, tbl_product_value.value_text is referenced by its interface member instead of its class member. If you change the declaration from

    public static void foo<T>(System.Data.Linq.Table<T> table) where T : class, IMyInterface

    to

    public static void foo<T>(System.Data.Linq.Table<T> table) where T : tbl_product_value, IMyInterface

    everything re-works fine. But this is useless in our case...

    I really feel that as a "missing little code part"(bug?) in the Microsoft's library.

     

    I don't understand what you mean by making this method static. Declaring foo as

    public static void foo<T>(System.Data.Linq.Table<T> table)

    doesn't change anything. There is no reference to class members in this example, but this is only an example.

     

    Thanks,

     

    Alain

    Wednesday, April 09, 2008 9:14 AM
  • Hi,

    to make sure I got it.

    Two tables

    Code Snippet

    CREATE TABLE [dbo].[TestTable1](

    [ID] [int] IDENTITY(1,1) NOT NULL,

    [Text] [nvarchar](50) NOT NULL,

    [Int1] [int] NOT NULL,

    ....

    CREATE TABLE [dbo].[TestTable2](

    [ID] [int] IDENTITY(1,1) NOT NULL,

    [Text] [nvarchar](50) NOT NULL,

    [Date2] [smalldatetime] NOT NULL,

    ....

     

     

    An interface and partial classes to access the field Text in both tables

    Code Snippet

    public interface IMyInterface

    {

    string Text { get; set; }

    }

     

    partial class TestTable2 :IMyInterface

    {

    }

     

    partial class TestTable1 :IMyInterface

    {

    }

     

     

    And a generic method in the program which can access the common field

    Code Snippet

    class Program

    {

    static void Main(string[] args)

    {

    DBDataContext DC = new DBDataContext();

    DC.Log = Console.Out;

    foo(DC.TestTable1s);

    foo(DC.TestTable2s);

    Console.ReadKey();

    }

    static void foo<T>(Table<T> table) where T : class, IMyInterface

    {

    // this will run

    var qry1 = from o in table.AsEnumerable<T>()

    // gives the exception

    var qry1 = from o in table

     where o.Text == "XYZ"

     select o;

    foreach (var item in qry1)

    {

    Console.WriteLine(item.Text);

    }

    }

    }

     

     

    var qry1 = from o in table

    gives the exeception and has an Sql of

    SELECT [t0].[ID], [t0].[Text], [t0].[Int1]
    FROM [dbo].[TestTable1] AS [t0]
    WHERE [t0].[Text] = 'XYZ'

     

    var qry1 = from o in table.AsEnumerable<T>()

    reads the whole table and (I guess) uses Linq To Objects to find the object

     

    The following will do the job too

    var qry1 = from o in table

    where o.Text.Equals("XYZ")

    select o;

    and again with the Sql

    SELECT [t0].[ID], [t0].[Text], [t0].[Int1]
    FROM [dbo].[TestTable1] AS [t0]
    WHERE [t0].[Text] = @p0
    -- @p0: Input NVarChar (Size = 3; Prec = 0; Scale = 0) [XYZ]
    -- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.21022.8

    XYZ

     

    I don't know what's wrong with

    var qry1 = from o in table

     where o.Text == "XYZ"

     select o;

     

    regards

    Philipp

     

    Wednesday, April 09, 2008 12:23 PM
  • Yes, calling .AsEnumerable() will do the job since it will retreive all the objects into an array or something before executing the .Where().
    But this is really not acceptable since we have set some DataLoadOptions to the context to automatically load related objects and accelerate the following calls. At the end, this would be equivalent to loading the whole database into memory... :-/

    Even better than that, if you take each elements one by one, it all works fine (see my first post of the thread):
                for( int i=0; i<query.Count(); ++i )
                {
                    var value = query.Skip(i).First();    //    <= This works fine ! (but really slow)
                }


    To be honest, I have already posted a similar thread (http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=3029845&SiteID=1) but received no real answer.
    Do you know where else I can ask?


    Many thanks,

    Alain
    Wednesday, April 09, 2008 1:57 PM
  • Hi,

     

    yes I understand your concerns about .AsEnumerable() (it was my first attempt).

     

    The more important point is that using

    var qry1 = from o in table

    where o.Text.Equals("XYZ")

    select o;

    will work.

    This is translated to

    SELECT [t0].[ID], [t0].[Text], [t0].[Int1]
    FROM [dbo].[TestTable1] AS [t0]
    WHERE [t0].[Text] = @p0
    -- @p0: Input NVarChar (Size = 3; Prec = 0; Scale = 0) [XYZ]
    -- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.21022.8

    and shows the right result.

     

    The funny thing is that 'where o.Text == "XYZ"' is translated to the same Sql statement (you can check this in Debugger) but gives the exeception message.

     

    regards

    Philipp

    Wednesday, April 09, 2008 3:34 PM
  • Yes, you are right, this seems to works ok. We will try to use .Equals() from now on.
    Still it would be better to warn MSFT about that since it may hide a bigger bug, no?


    Huge Thanks,

    Alain
    Wednesday, April 09, 2008 3:40 PM
  • Sure, can you change this thread to a bug report? If you choose another way can you please post a link here that I can keep track of it. I'm curious about the answer why == and .Equals()  are differ in the way they are processed.

     

    regards

    Philipp

    Wednesday, April 09, 2008 4:16 PM
  • "change this thread to a bug report"... well well well... yes yesyes... I would be pleased to do that but... erm... how exactly you do that? ;-)
    I looked around and in the FAQ but found no way. Google pointed me to connect.microsoft.com but this is to create a new bug from scratch...
    So, if you could point me to the
    "change this thread to a bug report" button, I would be happy to click on it :-D
    Or better so, if you want to do it, feel free ;-)
    Wednesday, April 09, 2008 4:53 PM
  • Sorry, I saw bug threads in the vb forums but this only a pilot project available there.

    If you want, I can report it at the connect site and attach my test files. I only need some time and i will post it here if I have done it.

     

    greetings

    Philipp

    Wednesday, April 09, 2008 7:54 PM
  •  

    GOOD...   the solution that use "Equals" instead of "=="  is good but reason is uncovered yet...

     

     

    highlight it.  Any internal expertise gives feedback ???..

    Monday, September 01, 2008 5:19 AM
  • Nope, sorry.

    Didn't took the time too search how to report bugs...

     

    Anyway, we are writing our own QueryProvider and '==' and '.Equals()' have a totally different representation internally. So this should be why...

     

    Alain
    Monday, September 01, 2008 9:13 AM
  • Mark up!  

    This is really a strange phenomenon that 'Equals' takes effect whereas '=='  shows little help. 

    Now i am intending to build some  'interface-supported' queries to  generalize many similar codes like



    where product.ProductId = XX  (  where T.EntityId = XX  )
    Tuesday, April 21, 2009 5:55 AM