Solved

How do I use a Lambda Select to return a specific data type?

Posted on 2014-10-13
10
80 Views
Last Modified: 2014-10-24
I have the following States table with a list of the US States.  I want a method that will return the list of states but just the State Abbreviation and State Name so it can be used in a drop down.  I am having a problem with formatting my lambda expression to give me what I want.

Here is what I have so far:

State Table definition generated by Entity Framework model
namespace CoreDataClass.Model
{
    using System;
    using System.Collections.Generic;
    
    public partial class State
    {
        public int StateId { get; set; }
        public string StateName { get; set; }
        public string StateAbbr { get; set; }
        public int DrcStateNbr { get; set; }
        public int UwStateId { get; set; }
    }
}

Open in new window


Here is my In-Memory representation of the State table to be used with Unit Testing:
namespace CoreDataTests.Repository
{
    class InMemoryCoreDataRepository : ICoreDataRepository
    {
        private List<State> _dbStatesTBL = new List<State>();
        private List<qpIndex> _dbqpIndexesTBL = new List<qpIndex>();

        public void Add(State recordToAdd)
        {
            _dbStatesTBL.Add(recordToAdd);
        }

        public int SaveChanges()
        {
            return 1;
        }

        public List<StateDropdown> GetStates()
        {
            var dbrecords = _dbStatesTBL.Select(st => new { StateAbbr = st.StateAbbr, StateName = st.StateName });
            // Throw error if no records are returned - this table should have records
            if (dbrecords == null || dbrecords.Count() == 0)
                throw new ApplicationException("States Table is empty");
            return dbrecords as List<StateDropdown>;
        }
    }
}

Open in new window


Unit Test:  (PopulateTable creates entries in the In Memory table)
        [TestMethod]
        public void GetStates_Returns_StateName_And_State_Abbreviation_In_StateName_Alphabetical_Order()
        {
            // Arrange
            InMemoryCoreDataRepository repository = PopulateTable();
            CoreData sut = new CoreData(repository);

            // Act
            var result = sut.GetStates();

            // Assert
            Assert.IsInstanceOfType(result, typeof(List<StateDropdown>));
            Assert.AreEqual(51, result.Count());                            // list contains Washington, DC
            StateDropdown firstState = result.ElementAt(0);
            StateDropdown lastState = result.ElementAt(50);
            Assert.AreEqual("ALASKA", firstState);
            Assert.AreEqual("WYOMING", lastState);   
        }

Open in new window


Unit Test fails with the following Error Message:
Assert.IsInstanceOfType failed.  Expected type:<System.Collections.Generic.List`1[CoreDataClass.Model.StateDropdown]>. Actual type:<(null)>.

When debugging, I get 51 when I print dbrecords.Count() which is what I am expecting (list includes Washington, DC).

I get the error when I try and Assert that the result is of type List<StateDropdown>.  Can anyone tell me what I am doing wrong?  Any help is greatly appreciated!
0
Comment
Question by:dyarosh
  • 5
  • 3
  • 2
10 Comments
 
LVL 9

Expert Comment

by:Beartlaoi
ID: 40377335
At the bottom of GetStates() you have
return dbrecords as List<StateDropdown>;
So you are casting a List<State> to List<StateDropdown>
How is StateDropdown defined?  Are you missing something that allows the cast to succeed?
0
 

Author Comment

by:dyarosh
ID: 40377413
Here is how StateDropdown is defined:
    public partial class StateDropdown
    {
        string StateAbbr;
        string StateName;
    }

Open in new window

0
 
LVL 9

Expert Comment

by:Beartlaoi
ID: 40377525
Thats partial, is there more to it?  
Anyway to help debug where I think the problem is change the last line in GetStates() from
return dbrecords as List<StateDropdown>;
to
List<StateDropdown> retVal = dbrecords as List<StateDropdown>;
if (retVal == null)
                throw new ApplicationException("Cast returned null");
return retVal;
0
Courses: Start Training Online With Pros, Today

Brush up on the basics or master the advanced techniques required to earn essential industry certifications, with Courses. Enroll in a course and start learning today. Training topics range from Android App Dev to the Xen Virtualization Platform.

 

Author Comment

by:dyarosh
ID: 40377583
I made the modifications you suggested and retVal is null.  dbrecords.Count() still returns 51.
0
 

Author Comment

by:dyarosh
ID: 40377586
Here is some debug output:

>? dbrecords.ElementAt(0)
{ StateAbbr = "AK", StateName = "ALASKA" }
    StateAbbr: "AK"
    StateName: "ALASKA"
>
0
 
LVL 62

Expert Comment

by:Fernando Soto
ID: 40377974
Hi dyarosh;

The StateDropdown class needs to have two public properties in order for the Linq query to fill them. I have also modified the Linq query itself.

public List<StateDropdown> GetStates()
{
    // I have modified the next line of code.
    var dbrecords = _dbStatesTBL.Select(st => new StateDropdown { StateAbbr = st.StateAbbr, StateName = st.StateName });
    
    // Throw error if no records are returned - this table should have records
    if (dbrecords == null || dbrecords.Count() == 0)
        throw new ApplicationException("States Table is empty");
        
    // I modified the next line of code.    
    return dbrecords.ToList();
}

// This class needs to have these two public properties
// So that the Linq query can fill them 
public partial class StateDropdown
{
    public string StateAbbr { get; set; }
    public string StateName { get; set; }
}

Open in new window

0
 

Author Comment

by:dyarosh
ID: 40391853
Here is my StateDropdown definition:
    public partial class StateDropdown
    {
        public string StateAbbr { get; set; }
        public string StateName { get; set; }
    }

Open in new window


Here is the change I made in the GetStates method:
var dbrecords = _dbStatesTBL.Select(st => new StateDropdown { StateAbbr = st.StateAbbr, StateName = st.StateName }).OrderBy(st => st.StateName).ToList();

Open in new window


I am getting the following errors:

'CoreDataClass.Model.StateDropdown' does not contain a definition for 'StateAbbr'
'CoreDataClass.Model.StateDropdown' does not contain a definition for 'StateName'

If I do the following I can access StateAbbr and StateName in StateDropdown:
StateDropdown std = new StateDropdown();
std.StateAbbr = "PA";
std.StateName = "Pennsylvania";

Open in new window


Any thoughts as to what I am doing wrong?
0
 
LVL 62

Expert Comment

by:Fernando Soto
ID: 40392156
Can you post the schema for the object _dbStatesTBL, please.
0
 
LVL 9

Accepted Solution

by:
Beartlaoi earned 500 total points
ID: 40392444
You need to fill-in the get and set members like this:
public string StateAbbr {
get { return this.StateAbbr; }
set { this.StateAbbr = value; }
}
public string StateName { 
get { return this.StateName; }
set { this.StateName= value; }
}

Open in new window

0
 

Author Closing Comment

by:dyarosh
ID: 40401829
I had to make the following changes because my unit tests were crashing (not failing but crashing) when I used your implementation.  Not sure why but implementing the private properties solved the problem.  Thank you for your help!


private string _StateAbbr;
public string StateAbbr {
get { return_StateAbbr; }
set { _StateAbbr = value; }
}
private string _StateName;
public string StateName {
get { return _StateName; }
set { _StateName= value; }
}
0

Featured Post

Live: Real-Time Solutions, Start Here

Receive instant 1:1 support from technology experts, using our real-time conversation and whiteboard interface. Your first 5 minutes are always free.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In order to hide the "ugly" records selectors (triangles) in the rowheaders, here are some suggestions. Microsoft doesn't have a direct method/property to do it. You can only hide the rowheader column. First solution, the easy way The first sol…
Introduction Hi all and welcome to my first article on Experts Exchange. A while ago, someone asked me if i could do some tutorials on object oriented programming. I decided to do them on C#. Now you may ask me, why's that? Well, one of the re…
Two types of users will appreciate AOMEI Backupper Pro: 1 - Those with PCIe drives (and haven't found cloning software that works on them). 2 - Those who want a fast clone of their boot drive (no re-boots needed) and it can clone your drive wh…
Email security requires an ever evolving service that stays up to date with counter-evolving threats. The Email Laundry perform Research and Development to ensure their email security service evolves faster than cyber criminals. We apply our Threat…

808 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question