webForumDet fria alternativet

Collection

.NETur .NET

26 svar · 923 visningar · startad av aleborg

Medlem sedan jan. 20013 341 inlägg
Frågan#1

Jag har en class som ser ut ungefär så här:

	public class getUser
	{
		private string username,email,sql;
		public getUser()
		{
			//hämtar connection strängen
		}
		public void selectUser(string id)
		{
			//selectsats för att hämta en användare
			sql="SELECT username, email FROM users WHERE userID="+id;
		}
		public string Username
		{
			get{return username;}
			set
			{
				if(value.Length>0)
					username = "username='" + value.Replace("'","''") +"',";
				else
					username = "";

			}
		}
		public string Email
		{
			get{return email;}
			set
			{
				if(value.Length>0)
					email = "email='" + value.Replace("'","''") +"',";
				else
					email = "";

			}
		}
		public void InsertUser()
		{
			sql="INSERT INTO users SET "+username+email;
			sql = sql.Remove(sql.Length-1,1);
			//lägger in i databasen
		}
		public void UpdateUser(string id)
		{
			sql="UPDATE users SET "+username+email;
			sql = sql.Remove(sql.Length-1,1);
			sql += " WHERE userID="+id;
			//lägger in i databasen
		}
	}

Den funkar precis som den ska, MEN om jag nu vill lägga till en collection i den här som returnerar alla users och deras användarnamn och email hur gör jag då?
Tanken är att det ka kunna användas för att fylla olika objekt med DataBind(), någon add eller remove behövs inte utan endast hämtning...

Medlem sedan apr. 20012 266 inlägg
#2
public class UserCollection : CollectionBase
{
	public void Add(getUser item)
	{
		List.Add(item);
	}

	public void Remove(getUser item)
	{
		List.Remove(item);
	}

	public getUser this[int Index]
	{
		get	{ return (getUser)List[Index]; }
		set	{ List[Index] = value; }
	}

	public UserCollection()
	{
		using(SqlDataReader reader = data.GetReader())
		{
			getUser user = new getUser();
			user.Username = (string)reader["username"];
			// osv
			List.Add(user);
		}
	}
}
Medlem sedan jan. 20013 341 inlägg
#3

min tanke var mer om man kunde ha det så här:

	public class getUser
	{
		private string username,email,sql;
		public getUser()
		{
			//hämtar connection strängen
		}
		public void selectUser(string id)
		{
			//selectsats för att hämta en användare
			sql="SELECT username, email FROM users WHERE userID="+id;
		}
		public string Username
		{
			get{return username;}
			set
			{
				if(value.Length>0)
					username = "username='" + value.Replace("'","''") +"',";
				else
					username = "";

			}
		}
		public string Email
		{
			get{return email;}
			set
			{
				if(value.Length>0)
					email = "email='" + value.Replace("'","''") +"',";
				else
					email = "";

			}
		}
		public void InsertUser()
		{
			sql="INSERT INTO users SET "+username+email;
			sql = sql.Remove(sql.Length-1,1);
			//lägger in i databasen
		}
		public void UpdateUser(string id)
		{
			sql="UPDATE users SET "+username+email;
			sql = sql.Remove(sql.Length-1,1);
			sql += " WHERE userID="+id;
			//lägger in i databasen
		}
		[b][blue]public void getUserCollection()
		{
			//hämtar och returnerar alla användare i databasen som collection
		}[/blue][/b]
	}

Är ju inte i behov av bl a remove osv. Hade varit mycket enklare och fåå in det i befintlig klass, går det?

Medlem sedan apr. 20012 266 inlägg
#4

du får nog ha två klasser, en getUser som jag skulle döpa till User eftersom den inte enbast hämtar en användare, sedan skulle du behöva en UserCollection. Denna kan du sedan från din funktion getUserCollection retunera.

Medlem sedan maj 20012 812 inlägg
#5

Du lägger in en massa saker i din class som inte skall vara där.

Din class skall vara så generell som möjligt. Du skall exempel viss inte ha någon funktion som hämtar en connectionsträng i din class, denna funktion skall ligga i ditt databaslager och inte i din class.

Sedan är frågan om din class skall kunna göra INSERT/UPDATE själv eller om man skall ha en UserManager som löser det till dig. Det tvistas rätt friskt om detta, själv är jag inne på att man har en Userclass som endast hanterar funktioner och varaibler relaterade till classen, alltså saker som: Namn, ålder, email osv osv.

Skapande och sparande av classen tar en generell DataManager hand om.

Denna kodsnutt tar och skapar och hämtar data från en databas till en Userklass

<code>
User user = new User(EnumSPName.LoadUser);
user.ID = 1;
DataManager.Load(user);
</code>

Följande kod gör en INSERT/UPDATE på objektet user i databasen
<code>
User user = new User(EnumSPName.SaveUser);
user.name = "Magnus";
user.email = "magnus@magnus.magnus";
user.age = 10;
DataManager.Save(user);
</code>

Här har jag nu en så "DUM" class som möjligt.

- Magnus

Medlem sedan jan. 20013 341 inlägg
#6

Jag tycker att min klass funkar ypperligt!
getUser.Username = "Weeee";
getUser.Password = "foo";
getUser.InsertUser()

och en ny användare är skapad!
eller

getUser.UpdateUser(15)
för att uppdatera!

Det här är en klass som endast min kodning kommer åt och jag slipper göra allt dubbelt! Att sätta samma variabler i en klass för update och en för insert skulle skapa ca 1500 rader kod till!
Den kod i exemplet är bara en pytteliten del av den verkliga koden som egentligen hanterar ca 200 databasposter i 3 tabeller som ska uppdateras/insertas/hämtas. var inne på att ha olika klasser först men la ner det ganska fort! Det som är smidigt är att SQL-satsen blir dynamisk och endast det som har blivit tilldelat nått kommer med i SQL-satsen.
Men hanterar man mindre data så är det klokt att göra som du säger!

Medlem sedan maj 20012 812 inlägg
#7

Jag skulle precis säga tvärtom, när man hanterar mycket data, och har många klasser, samt vill ha möjlighet att dela ut min klass till flera program så fungerar mitt exempel bäst.

Jag har inga speciella variabler för update eller insert, jag har min klass samt en DataManager som genererar kod utifrån min klass, jag slipper alltså skriva de extra funktioner InsertUser() / UpdateUser() på min klass. Detta ger mig mindre kod att skriva i min klass eftersom min DataManager genererar denna kod till mig.

Jag kan slänga in vilket objekt jag vill i min DataManager.Load() funktion så kommer den att hämta data från databasen och fylla mitt objekt med data.

Det är aldrig dumt/jobbigt att ha flera klasser. En klass kan beskrivas som ett substantiv. Och dess variabler som adjektiv(är det väl) och funktioner som verb.

Ta en stol, det blir en bra klass!

Ur ser den ut. Den kan ha olika antal ben, den kan ha olika färg alltså 2 adjektiv som blir 2 variabler.

int antalBen;
Color färg;

Vad kan en stol göra, inte mycket alltså har den inga funktioner! Kan en stol skapa sig själv, nope. Alltås har vi ingen InsertStol() funktion i den.

En bra beskrivning på hur man omvandlar verkligheten till OO. Nu finns det alltid undantag, ta din klass User. Kan den skapa sig själv, nope den behöver 2 andra Users för det, eller en UserManager(), kan en User ta koll på sig själv, Japp!

Betyder det att DeleteUser() skall ligga i Userklassen eller inte, för vår stol kan inte ta koll på sig själv, där måste vi ha en StolManager() klass som skapar och tar bort stolen. Skall vi då ha vissa klasser som kan ta bort sig själv, medans andra inte kan. Logiskt inte, alltså har man en Managerklass för alla klasser.

Det är som sagt omtvistat och vissa hävdare att en klass skall vara så DUM som möjligt och vissa hävdare att en klass visst kan skapa sig själv och ta bort sig själv.

Det hela betyder att man skriver mer kod i startskedet, men att man kan återanvända sig kod på ett smidigt sätt samt att man minskar risken för att andra applikationer använder funktioner som de inte är tänkta att använda.

Du gör givetviss som du vill och är du nöjd med din klass så behåll den.

- M

Medlem sedan jan. 20013 341 inlägg
#8

Skulle du kunna ge ett kod exempel så är det lättare att se hur du menar och bygger upp det!

Medlem sedan okt. 2002188 inlägg
#9

Gladh skrev:

Jag har inga speciella variabler för update eller insert, jag har min klass samt en DataManager som genererar kod utifrån min klass, jag slipper alltså skriva de extra funktioner InsertUser() / UpdateUser() på min klass. Detta ger mig mindre kod att skriva i min klass eftersom min DataManager genererar denna kod till mig.

Intresserad av hur du löst detta?

Gör ungefär likadant men tror inte min lösning är så bra.

Har gjort som så att varje klass har en mappningsklass som beskriver vad som skall sparas var. Denna skapar jag mha ett eget verktyg.

Dock har jag i varje klass en load och en save metod. Dessa anropar sedan en Datamanager klass.. så mina save metoder ser ut ungefär så här

public void Save()
{
IDataManager Dm = Datamanger.getDataManager(this);
Dm.Save(this);
}

Det sen datamanager gör är att kolla upp detta objektet. Hur såg det ut när det laddades?. Och sedan så skapar den en sqlsats som jag sedan kör. Fördelen är att om jag bara uppdaterar ett fält så kommer bara jag bara att uppdatera detta.

Medlem sedan maj 20012 812 inlägg
#10

Som jag har löste det så använder jag mig att attribute och reflextion.

Alltså min DataManager.Load(object) Tar emot ett object och med hjälp av reflextion och attributes så kan jag se om en variabel skall fyllas med data från databasen, jag kan även sätta vilka variabler som skall vara vilkorsvariabler vid Load resp Save i databasen.

Min klass ser typ ut så här:

class User{
 [SqlParameterLoad("@NAME")]
 [SqlParameterSave("@NAME")]
 [DatabasField("Name")]
 private string _name;

 [SqlParameterSave("@AGE")]
 [DatabasField("Age", 0)]
 private int _age;
}

Attribute har jag gjort själv och med hjälp av reflections så får jag fram vilka variabler som finns, på varje variable så kollar jag om ett attribute finns. Så om jag skall köra en SP så kollar jag vilka fält som har attributet [SqlParameter...] och skapar en parameter till min SP med värdet från variablen.

När jag skall läsa in data från en körd SP så kollar jag om ett fält har attributet [DatabasField] så fall skall den variablen få värdet från databasens column som har det namn som jag skickar med i min attributet. 0 i attributet [DatabasField] finns så jag vet vad jag skall ersätta NULL med eftersom en int inte kan ha värdet NULL.

Jag har inte orkat göra en mappingtabell än, men det kommer och då slipper jag kolla alla attribute varje gång (det tar ju performance) och kan istället kolla i min mappingtabell som jag skapar första gången som objektet efterfrågas.

Man kan även skippa SP och generera SQL strängar, vilket gör att man slipper skriva SP. Jag gillar dem dock så jag håller mig till dem.

Har för mig att jag slängt in kod på hur min DataManager klass ser ut, i tidigare post, sök så hittar du det nog.

- M

Medlem sedan jan. 20013 341 inlägg
#11

Ingen som vet hur man gör?
Lite mer kod för att det ska bli enklare att förstå hur jag gör:

	public class GetUserInfo
	{
		private string status,created_by,belongs_to,services,new_customer,contacts,contact_us;
		private string strConn,SQL;
		private string username,name,email,created,edited,language,password,level;
		public GetUserInfo()
		{
			Connect Conn = new Connect();
			strConn = Conn.ConnStr;
		}
		public bool SelectUser(string userid)
		{
			try
			{
				SQL= "SELECT users.userID"+					//user
					",users.username"+
					",users.name"+
					",users.email"+
					",users.created"+
					",users.edited"+
					",users.status"+
					",users.contacts"+
					",users.contact_us"+
					",users.language"+
					",users.created_by"+
					",users.belongs_to"+
					",users.services"+
					",users.new_customer"+
					",users.level"+
					" FROM users where UserID="+ userid;
				OdbcConnection ConnStr = new OdbcConnection(strConn);
				OdbcCommand cmdS = new OdbcCommand(SQL, ConnStr);
				ConnStr.Open();
				using(OdbcDataReader rS = cmdS.ExecuteReader(CommandBehavior.CloseConnection))
				{
					if(rS.Read())
					{
						//set private variables from the DB
						UserID = (string)rS["UserID"];
						username = (string)rS["username"];
						name = (string)rS["name"];
						email = (string)rS["email"];
						created = (string)rS["created"];
						edited = (string)rS["edited"];
						status = (string)rS["status"];
						contacts = (string)rS["contacts"];
						contact_us = (string)rS["contact_us"];
						language = (string)rS["language"];
						created_by = (string)rS["created_by"];
						belongs_to = (string)rS["belongs_to"];
						services = (string)rS["services"];
						level = (string)rS["level"];
						new_customer = (string)rS["new_customer"];
					}
				}
			}
			catch
			{return false;}
			return true;
		}
		public string Username
		{
			get{return username;}
			set
			{
				if(value.Length>0)
					username = "username='" + value.Replace("'","''") +"',";
				else
					username="";
			}
		}
		public string Password
		{
			get{return password;}
			set
			{
				if(value.Length>0)
					password = "password=password('" + value.Replace("'","''") +"'),";
				else
					password="";
			}
		}
		public string Name
		{
			get{return name;}
			set
			{
				if(value.Length>0)
					name = "name='" + value.Replace("'","''") +"',";
				else
					name = "";
			}
		}
//osv

till det här så behöver jag en collection som kan returnera alla users

Medlem sedan juli 20011 304 inlägg
#12

Det jag tror att du vill göra är att retunera en arraylist :)
En Collection är ett rätt så generellt uttryck.

Detta tror jag är ett relevant exempel som du kan titta på.

Medlem sedan juli 20011 304 inlägg
#13

Och vill du ha något som mer liknar ditt exempel där man bygger en Egen collection (ärver IEnumerator) kan du kika här

Medlem sedan jan. 20013 341 inlägg
#14

Provade att lägga in det här:

		public ArrayList ListResellers()
		{
			SQL= "SELECT users.userID"+					//user
				",users.username"+
				",users.name"+
				",users.email"+
				",users.created"+
				",users.edited"+
				",users.status"+
				",users.contacts"+
				",users.contact_us"+
				",users.language"+
				",users.created_by"+
				",users.belongs_to"+
				",users.services"+
				",users.new_customer"+
				",users.level"+
				" FROM users where level=1 AND new_customer=0";
 
			System.Collections.ArrayList al = new System.Collections.ArrayList();
			OdbcConnection conn = new OdbcConnection(strConn);
			conn.Open();
			OdbcCommand cmd = new OdbcCommand(SQL, conn);
			OdbcDataReader reader = cmd.ExecuteReader();
			while (reader.Read()) 
			{
				al.Add(reader.GetString(0).ToString());
				al.Add(reader.GetString(1).ToString());
				al.Add(reader.GetString(2).ToString());
				al.Add(reader.GetString(3).ToString());
				al.Add(reader.GetString(4).ToString());
				al.Add(reader.GetString(5).ToString());
				al.Add(reader.GetString(6).ToString());
				al.Add(reader.GetString(7).ToString());
				al.Add(reader.GetString(8).ToString());
				al.Add(reader.GetString(9).ToString());
				al.Add(reader.GetString(10).ToString());
				al.Add(reader.GetString(11).ToString());
				al.Add(reader.GetString(12).ToString());
				al.Add(reader.GetString(13).ToString());
				al.Add(reader.GetString(14).ToString());
			}
			return al;
		}

Men vet inte riktigt om det är rätt och hur jag sen ska kunna binda det till en repeater eller datagrid senare...

			GetUserInfo test = new GetUserInfo();
			ResellerList.DataSource = test.ListResellers();
			ResellerList.DataBind();

och repeatern(förenklad):

						<asp:Repeater id="ResellerList" runat="server">
							<ItemTemplate>
							<asp:Label ID="Username"></asp:Label>
							</ItemTemplate>
						</asp:Repeater>

Tanken är att binda Labeln till Username....

Medlem sedan juli 20011 304 inlägg
#15

Jag skulle skapa en UserInfo klass som jag fyller på från datareadern. Sen skulle jag lägga in varje UserInfo i arraylisten.

Nu innehåller ju din arraylist typ: {"username(från rad0)", "name(från rad2)", "email(från rad3)" ...}

Alternativt så får du fylla på varje element i arraylisten med en array. Har aldrig pysslat riktigt med det här så jag gissar lite så du får inte bli arg om det blir lite fel ;)

Medlem sedan jan. 20013 341 inlägg
#16

Någon mer som vet?

Medlem sedan sep. 20011 914 inlägg
#17

För att vidareutveckla Jons tänkande. (Känns som jag skrivit denna kod ett antal gånger. :) )

// UserInfo classen
public class UserInfo
{
   private string _username, _name, _email, _created;

   //Constructor
   public UserInfo(string username, string name, string email, string created)
   {
      this.username = username;
      this.name = name;
      this.email = email;
      this.created = created;
   }

   //Properties    
   public string username
   {
      get {return _username;}
      set {_username = value;}
   }

   public string name
   {
      get {return _name;}
      set {_name = value;}
   }

   public string email
   {
      get{return _email;}
      set{_email = value;}
   }

   public string created
   {
      get{return _created;}
      set{_created = value;}
   }
}

-----------------------------------------

// I ListResellers
...
while (reader.Read()) 
{
   al.Add(new UserInfo(reader.GetString(0).ToString(),reader.GetString(1).ToString(),reader.GetString(2).ToString(),reader.GetString(3).ToString()));
}
reader.Close()
return al;
...

------------------------------------------------------------------------

// Repeaterns ItemDataBound
private void repTest_ItemDataBound(Object Sender, RepeaterItemEventArgs e) 
{
   if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) 
   {
      UserInfo ui = (UserInfo)e.Item.DataItem;
      ((Label)e.Item.FindControl("lbTest")).Text = ui.username;
   }
}
Medlem sedan jan. 20013 341 inlägg
#18

Det här går inte alls :x

			<asp:Repeater id="ResellerList" runat="server">
				<ItemTemplate>
					<asp:Label ID="Username" AccessKey="Username" Visible="true" Runat="server"></asp:Label>
				</ItemTemplate>
			</asp:Repeater>
		private void ResellerList_ItemDataBound(Object Sender, RepeaterItemEventArgs e) 
		{
			if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) 
			{
				UserInfo ui = (UserInfo)e.Item.DataItem;
				((Label)e.Item.FindControl("Username")).Text = ui.username;
			}
		}
		private void InitializeComponent()
		{    
			this.ResellerList.ItemDataBound += new System.Web.UI.WebControls.RepeaterItemEventHandler(this.ResellerList_ItemDataBound);
			this.ResellerList.Load += new System.EventHandler(this.Page_Load);
			this.Load += new System.EventHandler(this.Page_Load);

		}
		public ArrayList ListResellers()
		{
			SQL= "SELECT users.userID"+					//user
				",users.username"+
				",users.name"+
				",users.email"+
				",users.created"+
				",users.edited"+
				",users.status"+
				",users.contacts"+
				",users.contact_us"+
				",users.language"+
				",users.created_by"+
				",users.belongs_to"+
				",users.services"+
				",users.new_customer"+
				",users.level"+
				" FROM users where level=1 AND new_customer=0";
 
			System.Collections.ArrayList al = new System.Collections.ArrayList();
			OdbcConnection conn = new OdbcConnection(strConn);
			conn.Open();
			OdbcCommand cmd = new OdbcCommand(SQL, conn);
			OdbcDataReader reader = cmd.ExecuteReader();
			while (reader.Read()) 
			{
				al.Add(new UserInfo(reader.GetString(0).ToString(),reader.GetString(1).ToString(),reader.GetString(2).ToString(),reader.GetString(3).ToString()));
			}
			reader.Close();
				return al;
		}
	}

	public class UserInfo
	{
		private string _username, _name, _email, _created;

		//Constructor
		public UserInfo(string username, string name, string email, string created)
		{
			this.username = username;
			this.name = name;
			this.email = email;
			this.created = created;
		}

		//Properties    
		public string username
		{
			get {return _username;}
			set {_username = value;}
		}

		public string name
		{
			get {return _name;}
			set {_name = value;}
		}

		public string email
		{
			get{return _email;}
			set{_email = value;}
		}

		public string created
		{
			get{return _created;}
			set{_created = value;}
		}
	}

Absolut inget kommer ut :(

Medlem sedan sep. 20011 914 inlägg
#19

Denna rad kan du väl ta bort?

this.ResellerList.Load += new System.EventHandler(this.Page_Load);
Medlem sedan jan. 20013 341 inlägg
#20

Gjorde ingen skillnad, den borde returnera 6 poster...

146 ms totalt · 3 externa anrop · v20260731065814-full.4bcf49fe
0 ms — hämta forumlista (cache)
0 ms — hämta statistik (cache)
143 ms — hämta tråd, inlägg och bilagor (db)