Wrox Programmer Forums
Go Back   Wrox Programmer Forums > C# and C > C# 2005 > C# 2005
| Search | Today's Posts | Mark Forums Read
C# 2005 For discussion of Visual C# 2005.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the C# 2005 section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old June 13th, 2007, 01:41 PM
Registered User
 
Join Date: Jun 2007
Location: , , .
Posts: 4
Thanks: 0
Thanked 0 Times in 0 Posts
Default Loading data into List<T>

How do I load data from an SQL database into a List<T> generic? I was thinking of creating a business object that inherits from List<T> but I can't seem to get it to work. The book is good at explaining the basics of this but I'm still not sure how I would use this kind of a generic in a real-world application. Is this something Microsoft forgot to handle?

 
Old June 13th, 2007, 02:39 PM
planoie's Avatar
Friend of Wrox
Points: 16,481, Level: 55
Points: 16,481, Level: 55 Points: 16,481, Level: 55 Points: 16,481, Level: 55
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Aug 2003
Location: Clifton Park, New York, USA.
Posts: 5,407
Thanks: 0
Thanked 16 Times in 16 Posts
Default

List<T> is the generic definition of the list, but you must specify the type you will use for the instance of the list. Decide what business class you want to use and create an instance of the list with your type as the type parameter:

List<MyBusinessClass> myList = new List<MyBusinessClass>();
MyBusinessClass myClassInstance;

myClassInstance = new MyBusinessClass();
//populate the instance members
myList.Add(myClassInstance);
//loop as needed


You can certainly extend List<T> if you wish as well. This is a good method of creating a custom collection. When you extend it, you can define the type of the list you are extending and all the List methods will apply that type parameter. This creates a strongly typed collection from a generic collection.

public class MyBusinessClassList : List<MyBusinessClass>{
   // add your members here
}

Alternatively, if you want to add capabilities to a generic list, but still maintain the generic capability, you can define your own generic type that derives from List<T>:

public class MyBusinessClassList<T> : List<T>{
   // add your members here
}

In this case however, you are still working in the context of a generic type, so you are limited in what you can do. However, if you constrain your definition you can work with some base type or interface.

-Peter
 
Old June 13th, 2007, 02:50 PM
Imar's Avatar
Wrox Author
Points: 70,322, Level: 100
Points: 70,322, Level: 100 Points: 70,322, Level: 100 Points: 70,322, Level: 100
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Jun 2003
Location: Utrecht, Netherlands.
Posts: 17,089
Thanks: 80
Thanked 1,576 Times in 1,552 Posts
Default

Hi rvincent,

You may want to take a look at my article series about N-Layer design. The series deals with List<T> classes and other design and data access issues. You find part 1 here:

http://Imar.Spaanjaars.Com/QuickDocId.aspx?quickdoc=416

Cheers,

Imar
 
Old June 13th, 2007, 07:34 PM
Registered User
 
Join Date: Jun 2007
Location: , , .
Posts: 4
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Quote:
quote:Originally posted by planoie
snip
I guess I need to explain further. Here's what I've created:

using System;
using System.Collections.Generic;
using System.Text;
using System.Data.SqlClient;
using GeoRange;

namespace GeoRange
{
    public class Targets : List<Target>
    {
        public List<Target> Load()
        {
            List<Target> data = new List<Target>();

            string connectionString = @"Server=E17818\SQLEXPRESS;Database=test;Trusted_C onnection=true";

            SqlConnection myConnection = new SqlConnection(connectionString);

            SqlCommand myCommand = new SqlCommand("SELECT Name FROM Targets", myConnection);

            myConnection.Open();

            SqlDataReader reader = myCommand.ExecuteReader();

            while (reader.Read())
            {
                Target Target1 = new Target();

                Target1.Name = reader["Name"] as string;

                //Target.X = reader["X"] as double;

                //Target.Y = reader["Y"] as double;

                data.Add(Target1);
            }

            myConnection.Close();

            myCommand.Dispose();

            return data; // not returning the List

        }
    }
}

//++++++++++++++++++++++++++++++++++++++++++++++++++ +++
//++++++++++++++++++++++++++++++++++++++++++++++++++ +++


using System;
using System.Collections.Generic;
using System.Text;

namespace GeoRange
{
    public class Target
    {
        private string _name;
        private double _X;
        private double _Y;

        public string Name
        {
            get
            {
                return _name;
            }
            set
            {
                _name = value;
            }
        }
        public double X
        {
            get
            {
                return _X;
            }
            set
            {
                _X = value;
            }
        }

        public double Y
        {
            get
            {
                return _Y;
            }
            set
            {
                _Y = value;
            }
        }

        public Target()
        {
        }

        public Target(string name, double X, double Y)
        {
            this._name = name;
            this._X = X;
            this._Y = Y;

        }



        }
    }

//++++++++++++++++++++++++++++++++++++++++++++++++++ +++
//++++++++++++++++++++++++++++++++++++++++++++++++++ +++

I then try to use these from a button on a form:

        private void button1_Click(object sender, EventArgs e)
        {

            List<Target> Targets = new List<Target>();

            Targets targetList = new Targets();
            targetList.Load();

            foreach (Target theTarget in targetList)
            {
                comboBox1.Items.Add(theTarget.Name);
            }

            //MessageBox.Show(Target1.Name, "A caption");
        }

This last part is the problem. targetList isn't returning the list. Anyone know why?

 
Old June 14th, 2007, 02:43 AM
joefawcett's Avatar
Wrox Author
Points: 9,763, Level: 42
Points: 9,763, Level: 42 Points: 9,763, Level: 42 Points: 9,763, Level: 42
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Jun 2003
Location: Exeter, , United Kingdom.
Posts: 3,074
Thanks: 1
Thanked 38 Times in 37 Posts
Default

That is the most confusing few lines of code I've ever seen.
You create a new class Targets, which derives from List<Target>. You then create an instance of List<Target> also called Targets. You then create an instance of Targets called targetList.
You then do
Code:
foreach (Target theTarget in targetList)
where you create an instance of Target called theTarget for each Target in targetList.

My head's spinning...

Your method Load returns a List<Target> but you don't actually save the return when you call it.
Why don't you store the data in a private List<Target> instead of returning it?
Have you stepped through the Load method to see if data is being populated?



--

Joe (Microsoft MVP - XML)
 
Old June 14th, 2007, 08:52 AM
planoie's Avatar
Friend of Wrox
Points: 16,481, Level: 55
Points: 16,481, Level: 55 Points: 16,481, Level: 55 Points: 16,481, Level: 55
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Aug 2003
Location: Clifton Park, New York, USA.
Posts: 5,407
Thanks: 0
Thanked 16 Times in 16 Posts
Default

Quick Joe! Bite the rope, BITE THE ROPE!! ;)

rvincent,

Joe has a point... Your code is a little confusing. That's the reason I use variable prefixing. I try to avoid naming variables with names that could conflict with class names (if not programmatically, then humanly).

As far as the problem goes... you need to either load the list you are extending or handle the return value of the Load() method as Joe mentioned.

I think what you need is this:
Code:
namespace GeoRange
{
    public class Targets : List<Target>
    {
        public Targets Load()
        {
            //you are deriving a list so don't create one internally
            <s>List<Target> data = new List<Target>();</s>
            ...
            while (reader.Read())
            {
                Target Target1 = new Target();
                ...
                this.Add(Target1); // Add the Target to the derived list.
            }
            ...
            return this; //return myself, even though we don't really need to
        }
    }
}

    private void button1_Click(object sender, EventArgs e)
    {
        //this was redundant
        <s>List<Target> Targets = new List<Target>();</s>

        Targets targetList = new Targets();
        //because the Load method loads the object itself,
        //you don't really need to do anything with the return value
        targetList.Load(); 
        ...
    }
-Peter
 
Old June 14th, 2007, 10:17 AM
Registered User
 
Join Date: Jun 2007
Location: , , .
Posts: 4
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Quote:
quote:Originally posted by joefawcett
 That is the most confusing few lines of code I've ever seen.
You create a new class Targets, which derives from List<Target>. You then create an instance of List<Target> also called Targets. You then create an instance of Targets called targetList.
You then do
Code:
foreach (Target theTarget in targetList)
where you create an instance of Target called theTarget for each Target in targetList.

My head's spinning...

Your method Load returns a List<Target> but you don't actually save the return when you call it.
Why don't you store the data in a private List<Target> instead of returning it?
Have you stepped through the Load method to see if data is being populated?



--

Joe (Microsoft MVP - XML)
Well, I am just learning. Thanks for making me feel like an idiot.

 
Old June 14th, 2007, 10:20 AM
Registered User
 
Join Date: Jun 2007
Location: , , .
Posts: 4
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Quote:
quote:Originally posted by planoie
 Quick Joe! Bite the rope, BITE THE ROPE!! ;)

rvincent,

Joe has a point... Your code is a little confusing. That's the reason I use variable prefixing. I try to avoid naming variables with names that could conflict with class names (if not programmatically, then humanly).

As far as the problem goes... you need to either load the list you are extending or handle the return value of the Load() method as Joe mentioned.

I think what you need is this:
Code:
namespace GeoRange
{
    public class Targets : List<Target>
    {
        public Targets Load()
        {
            //you are deriving a list so don't create one internally
            <s>List<Target> data = new List<Target>();</s>
            ...
            while (reader.Read())
            {
                Target Target1 = new Target();
                ...
                this.Add(Target1); // Add the Target to the derived list.
            }
            ...
            return this; //return myself, even though we don't really need to
        }
    }
}

    private void button1_Click(object sender, EventArgs e)
    {
        //this was redundant
        <s>List<Target> Targets = new List<Target>();</s>

        Targets targetList = new Targets();
        //because the Load method loads the object itself,
        //you don't really need to do anything with the return value
        targetList.Load(); 
        ...
    }
-Peter
Thanks. That really helps me as I learn this.

 
Old June 14th, 2007, 11:27 AM
joefawcett's Avatar
Wrox Author
Points: 9,763, Level: 42
Points: 9,763, Level: 42 Points: 9,763, Level: 42 Points: 9,763, Level: 42
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Jun 2003
Location: Exeter, , United Kingdom.
Posts: 3,074
Thanks: 1
Thanked 38 Times in 37 Posts
Default

Quote:
quote:Originally posted by rvincent

Well, I am just learning. Thanks for making me feel like an idiot.

That wasn't my intention, I was pointing out how difficult it is to follow the code the way it is written. If you are just beginning you have started with a fairly advanced topic, generics, inheritance and data access.
I would question the value of the derived class at all. You are tying yourself down somewhat especially having a SQL connection inside the class.
I would just use a List<T> to hold the Target instances. I would then have a helper class to perform the data access and return the appropriate DataReader. You can then loop through the reader and create the separate Target instances and add them to List<Target>:
Code:
DataReader dr = GetTargetDataReader(); //implement this method.
List<Target> targets = new List<Target>();
/*Loop through dr and for each row create a Target*/
while (dr.Read())
{
   Target target = new Target();
   target.Name = reader["Name"] as string;
   targets.Add(target);
}
Alternatively go with your derived class TargetList deriving from List<Target> but change the Load method to accept a DataReader, this is a more flexible solution. During Load you just add Target instances to the underlying list by using the Add method.
Another option would be to write your own Collection class that just delegates all calls to a private List<Target>.

--

Joe (Microsoft MVP - XML)




Similar Threads
Thread Thread Starter Forum Replies Last Post
generic List<T> Sort() shadowcodes C# 2005 2 February 15th, 2007 01:30 PM
How to implement a function return List<T> jdang67 C# 2005 2 January 30th, 2006 11:28 AM
<style> tags in a <body> vs. <div> bcat BOOK: Beginning CSS: Cascading Style Sheets for Web Design ISBN: 978-0-7645-7642-3 1 March 27th, 2005 08:50 AM
<marquee><b>About CHAT App. in PHP4</b></marquee> Ramkrishna PHP How-To 1 September 11th, 2004 07:01 AM
the book <<Data-Centric.net programing with c#>> jamxx All Other Wrox Books 0 November 18th, 2003 10:56 PM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.