locked
Azure TableEntity Inheritance Unexpected behavior RRS feed

  • Question

  • I am writing an application that uses a class that inherits from Microsoft.WindowsAzure.Storage.Table.TableEntity. There seems to be an issue with Inheritance when casting a generic table query of my type to a generic table query of type TableEntity. I would love to find out why this acts differently than normal inheritance if it is. 

    The problem exists in the code sample below. Create a new console app in C# vs2012 using the reference for Microsoft.WindowsAzure.Storage version 2.0. You also have to import Nuget package odata.lib (Not needed when compiling)

    The two compiler errors you will get from this code are.

    Error    2    Argument 2: cannot convert from 'Microsoft.WindowsAzure.Storage.Table.TableQuery<ConsoleApplication2.myTableEntitiy>' to 'Microsoft.WindowsAzure.Storage.Table.TableQuery<Microsoft.WindowsAzure.Storage.Table.TableEntity>'    c:\users\00602665\documents\visual studio 2012\Projects\ConsoleApplication2\ConsoleApplication2\Program.cs    19    64    ConsoleApplication2

    and

    Error    1    The best overloaded method match for 'ConsoleApplication2.Program.getFullListOfEntitiesByFilter(Microsoft.WindowsAzure.Storage.Table.CloudTable, Microsoft.WindowsAzure.Storage.Table.TableQuery<Microsoft.WindowsAzure.Storage.Table.TableEntity>)' has some invalid arguments    c:\users\00602665\documents\visual studio 2012\Projects\ConsoleApplication2\ConsoleApplication2\Program.cs    19    30    ConsoleApplication2

    My source code is as follows:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Microsoft.WindowsAzure.Storage;
    using Microsoft.WindowsAzure.Storage.Table;
    using Microsoft.WindowsAzure.Storage.Auth;

    namespace ConsoleApplication2
    {
        class Program
        {
            static void Main(string[] args)
            {
               TableQuery<myTableEntitiy> query = new TableQuery<myTableEntitiy>().Where(TableQuery.GenerateFilterCondition("", QueryComparisons.Equal, ""));
               TableQuery<TableEntity> query2 = new TableQuery<TableEntity>().Where(TableQuery.GenerateFilterCondition("", QueryComparisons.Equal, ""));
               CloudTable ct = new CloudTable(new Uri(""), new StorageCredentials("") );
               var DoesNotWork = getFullListOfEntitiesByFilter(ct, query);
               var Works = getFullListOfEntitiesByFilter(ct, query2);      
            }

            public static List<TableEntity> getFullListOfEntitiesByFilter(CloudTable table, TableQuery<TableEntity> query)
            {
                throw new NotImplementedException();
            }
        }

        class myTableEntitiy : TableEntity
        {
            public string test {get; set;}

        }
    }

    Tuesday, May 28, 2013 8:52 PM

Answers

All replies

  • Hi,

    The custom entity class is derived from TableEntity. You need to set the partitionkey and rowkey, the property must be public and must expose a parameter-less constructor:

    http://www.windowsazure.com/en-us/develop/net/how-to-guides/table-services/

    Please compare the sample code to see if you did all.

    Thanks,


    QinDian Tang
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Wednesday, May 29, 2013 6:24 AM
  • Hello,

    The code sample above is not expected to work or do anything useful.  It is intended to demonstrate a problem we are having getting code that should be correct to compile.  The actual program we have works fine because we implemented a workaround for this.

    To respond to your reply, how would the compiler know if you will be performing those things at runtime?  The above code doesn't compile even though the myTableEntity class inherits from TableEntity and we are tying to find out why.  You can see it yourself in VS.

    Can you tell us why passing a variable which is of a child class doesn't work with a function that expects an argument of the parent class?  In the above code sample, we are passing the variable query which is a TableQuery<myTableEntitiy> to a function that expects a TableQuery<TableEntity> and it is not compiling.  However, you can see that the definition of myTableEntitiy is merely a TableEntity with an extra property on it so it should have all the default behavior.

    If I have a function that expects an argument of class Animal, I should be able to pass it a Dog and it will compile (assuming that Dog inherits from Animal).  With the Azure SDK TableQuery<TableEntity>, why isn't this working?

    Wednesday, May 29, 2013 2:33 PM
  • In .NET Framework 4, covariance and contravariance are restricted to generic interfaces and generic delegates. Hence, you cannot implicitly convert TableQuery<myTableEntity> to TableQuery<TableEntity>. For more information, please refer to Covariance and Contravariance in Generics and Covariance and Contravariance (C# and Visual Basic).
    Wednesday, May 29, 2013 5:00 PM
  • Thanks for the very specific and useful response.  It appears we have some reading to do!
    Wednesday, May 29, 2013 5:19 PM