tags:

views:

79

answers:

3

I am trying to formulate a LINQ query to select a sublist of a list where it meets a where condition like so:

List<Entities.Base> bases = this.GetAllBases();
List<Entities.Base> thebases = from aBase in bases
                               where aBase.OfficeCD == officeCD
                               select aBase;

where Base is just an Entity class:

public string BaseCD { get; set; }
        public string BaseName { get; set; }
        public string OfficeCD { get; set; }
        public DateTime EffectiveDate { get; set; }
        public DateTime ExpirationDate { get; set; }

I am getting an error "Cannot implictly convert type System.Collections.Generic.IEnumerable to System.Collections.Generic.List

So I tried to apply the Cast operator but that fails. I see now that I am not tring to convert the type of the element. How can I solve this issue? Thanks!

+5  A: 

This is not really a problem that can be solved by "casting"; the result of the query you've got isn't a list - it's a deferred-executing sequence that will stream the matching items out on demand. You will have to actually load these results into aList<T>to achieve your purpose. For example, the Enumerable.ToListmethod will create a new list, populate it with the results of the query and then return it.

A few options:

var thebases = (from aBase in bases
                where aBase.OfficeCD == officeCD
                select aBase).ToList();

// fluent syntax
var thebases = bases.Where(aBase => aBase.OfficeCD == officeCD)
                    .ToList();

// not a LINQ method - an instance method on List<T>. 
// Executes immediately - returns a List<T> rather than a lazy sequence
var thebases = bases.FindAll(aBase => aBase.OfficeCD == officeCD);

// "manual" ToList()
var theBases = new List<Entities.Base>();
var matchingBases =  from aBase in bases
                     where aBase.OfficeCD == officeCD
                     select aBase;

foreach(var matchingBase in matchingBases)
   theBases.Add(matchingBase);
Ani
Thanks! I just thought of something - deffered execution. These queries will not execute until they are enumerated. I am building these into a DataLayer that returns the queries. Suppose I pick your first one and have:public List<Entities.Base> GetBasesForFieldOfficeCD(string officeCD) { List<Entities.Base> bases = this.GetAllBases(); List<Entities.Base> thebases = (from aBase in bases where aBase.OfficeCD == officeCD select aBase).ToList(); return thebases; } –Do I need to enumerate/execute the queries before return?
Sam Gentile
`ToList()` will do the enumeration for you. The final result: a 'normal' data-structure, not a query. Basically, a list doesn't remember how it was created. On the other hand, you may *prefer* that your `GetBasesForFieldOfficeCD` method return a deferred-executing query instead. In this case, make the return type 'IEnumerable<Entitities.Base>` and remove the call to `ToList()`.
Ani
+1  A: 

In addition to the method @Ani mentioned, you can also use LINQ to select the data directly into your classes like this:

List<Entities.Base> bases = this.GetAllBases(); 
List<Entities.Base> thebases = new List<Entities.Base>(
                            from aBase in bases  
                            where aBase.OfficeCD == officeCD  
                            select new Entities.Base {
                                BaseCD = aBase.BaseCD,
                                BaseName = aBase.BaseName,
                                OfficeCD = aBase.OfficeCD,  
                                EffectiveDate = aBase.EffectiveDate,  
                                ExpirationDate = aBase.ExpirationDate

                        };  
Joel Etherton
I don't think he wants a `select new Entities.Base` because that creates all new objects with the same contents as the old objects. He most likely wants the same objects to populate both lists.
Gabe
@Gabe - Possibly. I agree with Ani's answer (hence the credit), but wanted to put forth a different option for consideration.
Joel Etherton
+1  A: 

Here's a variant on Joel's answer that reuses the original entities for the new list instead of cloning them:

List<Entities.Base> bases = this.GetAllBases();  
List<Entities.Base> thebases = new List<Entities.Base>( 
                            from aBase in bases   
                            where aBase.OfficeCD == officeCD   
                            select aBase);  
Gabe