none
Expression problem RRS feed

  • Question

  • Hi,

    I am facing an weird problem. I have two classes MyClass and MyClass2 and a mapping function "Map" that create a MyClass2 object from a MyClass object. I would like to select objects MyClass2 using a list of MyClass. Well, it's hard to explain, but just take a look at my code that you will understand what I am talking about.

    The mapping function is:

    public Expression<Func<MyClass, MyClass2>> Map()
    {
       return o => new MyClass2
       {
           MyInteger = o.Integer
       };
    }


    I am trying to use it using the code:

    this.MyList = new List<MyClass>();
    
    this.MyList.Add(new MyClass { Integer = 1, Decimal = 10.5M });
    this.MyList.Add(new MyClass { Integer = 2, Decimal = 12.5M });
    
    IQueryable<MyClass2> res = this.MyList.Select(Map());
    
     

    BUT... I am getting the error message: "The type arguments for method System.Linq.Enumerable.Select<TSource, TResult>(System.Collections.Generic.IEnumerable<TSource>,System.Func<TSource,int,TResult>) cannot be inferred from the usage. Try specifying the type arguments explicitly." in the line "IQueryable<MyClass2> res = this.MyList.Select(Map());'"

    Does anybody knows what is wrong?
    Bruno Nepomuceno
    Monday, May 18, 2009 7:27 PM

All replies

  • There isn't a Select extension method on IEnumerable<T> that takes an Expression<Func<T, TResult>> as a parameter, so you have two options here.

    1. You change Map() to return a Func<MyClass, MyClass2> instead of an Expression<Func<MyClass, MyClass2>>.
    2. You can call MyList.AsQueryable() before calling Select. IQueryable has extension methods that will allow you to pass an Expression<T>.

    If all you need is the ability to execute this on a list of objects (without involving any APIs that use IQueryable, like LINQ to SQL), then #1 is probably better.
    Tuesday, May 19, 2009 1:11 AM
    Answerer
  • Just out of curiosity what problem does this solve?

    This reminds me of using the expliciit keyword to cast one object type to another, (I detail it on my blog here Explicit Keyword a different Copy Constructor ). Is this something than can be done outside of Linq per-se?
    William Wegerson (www.OmegaCoder.Com)
    Tuesday, May 19, 2009 1:24 PM
    Moderator
  • Hi David, first of all, thank you very much for you answer. Your solution works for simple collections, but when I try to use it with EntitySet properties, I am getting a "Unsupported overload used for query operator 'Select'." error. To create the list of products in the Category class, I have tried IList<Product>, IQueryable<Product>  and Rob Conery's LazyList (LazyList<Product>) (http://blog.wekeroad.com/blog/lazy-loading-with-the-lazylist/).  The code with problem is:

            public IQueryable<Category> All()
            {
                IProdutoRepository productRepository = L2SRepositoryFactory.Instance.CreateProductRepository();
    
                var categories = from c in dataContext.Categories
                                 select new Category
                                 {
                                     ID = c.ID,
                                     Description = c.Description,
                                     Products = c.Products.AsQueryable().Select(this.GetEntity())
                                 };
    
                return categories;
            }
    
            protected Expression<Func<Unipam.Patterns.LinqToSQLRepository.Model.Product, Product>> GetEntity()
            {
                return p => new Product
                {
                    ID = p.ID,
                    Description = p.Description
                };
            }



    Bruno Nepomuceno
    Tuesday, May 19, 2009 5:50 PM
  • Hi, Omegaman, well, what I'd like to do is: I want to use Linq to SQL but, I want to be independent from the L2S model. So, I have created model classes (poco). In my repositories, I would like to return objects from the POCO classes instead of L2S classes. So I've created mapping methods. Probably I will refactor it and place it in another class, but, for now, I am just making simple tests.

    Bruno Nepomuceno
    Tuesday, May 19, 2009 5:55 PM
  •  I want to be independent from the L2S model. So, I have created model classes (poco). In my repositories, I would like to return objects from the POCO classes instead of L2S classes. So I've created mapping methods. Probably I will refactor it and place it in another class, but, for now, I am just making simple tests.

    Bruno Nepomuceno
    Maybe I am off key here...but why not have the LS2 classes derive from a specific interface, easily done in a separate file away from the generated classes thanks to the partial construct, and have all the business logic only operate on the interface. Hence the actual source is immaterial to the business user, only that the contract of the interface being upheld by what is being worked with. ???


    William Wegerson (www.OmegaCoder.Com )
    Tuesday, May 19, 2009 6:45 PM
    Moderator
  •  I want to be independent from the L2S model. So, I have created model classes (poco). In my repositories, I would like to return objects from the POCO classes instead of L2S classes. So I've created mapping methods. Probably I will refactor it and place it in another class, but, for now, I am just making simple tests.

    Bruno Nepomuceno
    Maybe I am off key here...but why not have the LS2 classes derive from a specific interface, easily done in a separate file away from the generated classes thanks to the partial construct, and have all the business logic only operate on the interface. Hence the actual source is immaterial to the business user, only that the contract of the interface being upheld by what is being worked with. ???


    William Wegerson (www.OmegaCoder.Com )

    Well... but what should I do with the EntitySet and EntityRef properties? I would like to use IList or LazyList as property types. And besides, I don't know, I don't feel confortable using model classes as interfaces. Is it right?

    Bruno Nepomuceno
    Tuesday, May 19, 2009 6:56 PM
  • I took the tact that there is an end operation/user which wants the raw data and inferred that maybe you wanted a way to not be locked solely in Linq-to-sql objects for that processing .

    But from what you state here its apparent that you don't want to be too far removed ( or my understanding of your ultimate end goal is not on par with yours), so my advice may not be what is needed.
    William Wegerson (www.OmegaCoder.Com)
    Tuesday, May 19, 2009 7:30 PM
    Moderator
  • Hi OmegaMan,

    You're completely right, as you said, I don't want to be "locked in L2S", but thanks a lot for the reply! Maybe David has something to say about it :)

    Bruno Nepomuceno
    Tuesday, May 19, 2009 7:41 PM
  • There isn't a Select extension method on IEnumerable<T> that takes an Expression<Func<T, TResult>> as a parameter, so you have two options here.

    1. You change Map() to return a Func<MyClass, MyClass2> instead of an Expression<Func<MyClass, MyClass2>>.
    2. You can call MyList.AsQueryable() before calling Select. IQueryable has extension methods that will allow you to pass an Expression<T>.

    If all you need is the ability to execute this on a list of objects (without involving any APIs that use IQueryable, like LINQ to SQL), then #1 is probably better.

    Well... from what I've read, the problem is I can't use a EntitySet as an IQueryable. Due to this fact, I can't have an expression in my Select method. But, how to do it? I mean, how to implement something that make an EntitySet queryable? Anyone?
    Bruno Nepomuceno
    Tuesday, May 19, 2009 8:51 PM