3

I have the following model class :-

public class CustomerCustomAssetJoin
{
    public CustomAsset CustomAsset  { get; set; }
    public ICollection<CustomAsset> CustomAssets { get; set; }

} 

But when i wrote the following method:-

public CustomerCustomAssetJoin CustomerCustomAsset(string customerName)
{
    var customerAssets = tms.CustomAssets.Include(a => a.CustomAssetType).Where(a => a.CustomerName.ToLower() == customerName.ToLower());
    CustomerCustomAssetJoin caj = new CustomerCustomAssetJoin
    {
         CustomAsset = new CustomAsset {CustomerName = customerName },
         CustomAssets = customerAssets
    };
    return caj;  
 }

I got the following exception :

Error 20 Cannot implicitly convert type 'System.Linq.IQueryable' to 'System.Collections.Generic.ICollection'. An explicit conversion exists (are you missing a cast?)

So what is causing this error? To overcome this error i just add a .toList() as follows:

var customerAssets = tms.CustomAssets.Include(a => a.CustomAssetType).Where(a => a.CustomerName.ToLower() == customerName.ToLower());

So why do I have to convert it to a list?

Marco
  • 22,856
  • 9
  • 75
  • 124
  • ICollection and IQueryable are different things. http://stackoverflow.com/questions/4455428/difference-between-iqueryable-icollection-ilist-idictionary-interface – Gecko Nov 27 '13 at 12:07

3 Answers3

7

What you have stored in the customerAssets is just a query - a way, how to get the data. It's not the data itself yet, because it's lazily evaluated. ICollection<T> is an interface built for manipulating data collections that you already have. The query does not implement it, so you cannot implicitly convert from IQueryable<T> to the ICollection<T> Calling ToList() is a simple way how to force loading the data into an ICollection<T>, but it also means in your case, that at that place in code (and execution time) the query will get executed and data will be loaded from whatever database you are querying.

Honza Brestan
  • 10,637
  • 2
  • 32
  • 43
2

It's because you defined your CustomAssets as ICollection<CustomAsset>, while an IQueryable<T> does not implement any ICollection<T>. You need a result implementing ICollection<CustomAsset>, when you apply ToList(), it will convert to a List<CustomAsset> which in fact implements ICollection<CustomAsset>

King King
  • 61,710
  • 16
  • 105
  • 130
  • @JohnJohn yes, unless you redefine your `CustomAssets` to `IQueryable`, using `ToList()` of course will run the query right and get the items for you. – King King Nov 27 '13 at 12:30
1

This is because the LINQ Include method returns an object of type ObjectQuery(T) which implements the IQueryable<T> interface whereas your class is expecting an object which implements the ICollection<T> interface. As both these objects cannot be implicitly converted from one to the other you have to explicitly convert the result of the Include method to a List type, which does implement the ICollection<T> interface.

James
  • 2,195
  • 1
  • 19
  • 22