webForumDet fria alternativet

Liten fråga, arkitektur

.NET

13 svar · 878 visningar · startad av echoSwe

Medlem sedan nov. 20041 189 inlägg
Frågan#1

Tja

Jag har en klass - "BlogEntry.cs" som innehåller en massa strängar - diverse attribut till varje bloginlägg alltså. En är strängen "categories" som är en sträng som mitt affärslager/providerlayer har skapat genom att lägga ihop namnen på de kategorier som mitt inlägg tillhör.

Nu så upptäcker jag att min BlogEntry.cs börjar växa till sig, vilket är något jag inte vill, eftersom jag även använder den här klassen genom att skicka den/en instans av den från presentationslagret/datainhämtningslagret till affärslagret för att den sedan ska läggas till i databasen.

Mina kategorier är i en tabell i databasen med två fält, "id" och "name" och vad jag sitter och klurar på är alltså om det är smartare att skapa en publik metod i BlogEntry.cs som hämtar datan från databasen, dvs vilka kategorier som ett visst inlägg tillhör, varje gång den ihoplagda strängen över kategorierna önskas, eller om jag ska ha parallella string/array för att hantera värdena från min ListBox på tillfredställande sätt.

Detta är vad jag har om jag har parallella strängar:

    private string category;
    public string Category
    {
        get { return category; }
        set { category = value; }
    }
	private string[,] categoryArray; //[id, name]
	public string[,] CategoryArray 
	{
		get { return categoryArray; }
		set { categoryArray = value; }
	}

men om jag istället skapar en funktion som hämtar datan ur databasen via affärslagrets publika fuktion: "GetCategories" som returnerar en DataTable som jag , så kan jag istället ha en publik funktion i BlogEntry.cs som konkatenerar de kategorier från min datatable som ett visst inlägg tillhör när detta krävs, och när man istället skapar ett inlägg så låter man databasen hämta de kategorier och (affärslagret) lägga in dem i BlogEntry's array. När man skapar en BlogEntry för att lägga in i databasen sedan, så låter man presentationslagret lägga in varje kategori som inlägget tillhör i denna array, som sedan loopas igenom för att uppdatera referenstabellen i databasen via Affärslager-->DAL.

IDbCommand oCmd = ...GetCommmand();
IDbParameter
for (int i=0;i<entry.CategoryArray.length;i++) {
oCmd.CommandString = "INSERT bla bla " + entry.CategoryArray *+ " INTO blog_cats2entry";
oPrm. bla bla
oCmd.Parameters.Add(oPrm);
oDal.ExecuteNonQuery(oCmd);
}

Vad tycks om det? Nackdelen med detta är ju i så fall att min BlogEntry.cs blir beroende av mitt affärslager och inte längre representerar en post i databasen, utan är mer "sitt eget objekt".*

Medlem sedan nov. 20041 189 inlägg
#2

Undrar även varför det här inte funkar (första if-satsen), eller om jag ska använda mig av det datatable som redan har hämtats från databasen...

private string[,] FillCategories(string[] categoryIds) {
	BlogEntryComponent o = new BlogEntryComponent();
	System.Data.DataTable oDt = new System.Data.DataTable(); oDt = o.GetCategories();
	string[,] categories = new string[100, 100]; int counter = 0;
	foreach (System.Data.DataRow row in oDt.Rows)
	{
		if (row["id"].ToString().IndexOfAny(categoryIds) != -1)
		{
			categories[counter, counter] = { {row["id"].ToString(), row["name"].ToString()} };
			counter++;
		}
	}
}
Medlem sedan nov. 20041 189 inlägg
#3

Jag behöver fortfarande hjälp...

Ska jag använda en datatable för kategorierna? En enumerator (enum)? En struct? En List? En Array? En ArrayList?

Om det hjälper så bifogar jag ett diagram över blogmotorn som den är just nu...

Blog.jpg
Medlem sedan maj 20012 812 inlägg
#4

En är strängen "categories" som är en sträng som mitt affärslager/providerlayer har skapat genom att lägga ihop namnen på de kategorier som mitt inlägg tillhör.

Varför måste ditt blogentry vet vilken kategori den tillhör. Det är väl ganska ointressant för den? Jag hade inte lagt in den informationen i min blogentry. Utan istället lagt en relationstabell i databasen, då du har en många-till-många relation mellan blogentry och kategorier. Så när du vill visa en kategori, så hämtar du alla blogentrys som är kopplade till den kategorin, och när du hämtar en annan kategori så hämtar du alla blogentrys som är kopplade till den kategorin, det kan ju vara samma blogentry, men det är inget som blogentryn vet eller bryr sig om...

- M

Medlem sedan nov. 20041 189 inlägg
#5

Tjena Gladh!

Ja, jag har redan designat databasen på det sättet. Men sedan när man ska visa informationen tänkte jag att om en enda instans av mitt blog entry innehåller all information som presentationslagret kan tänkas vilja ha - dvs även en sträng med vilka kategorier som inlägget tilhör så slipper man sitta med SQL i presentationslagret...

Såhär blev det:

 public string Category
{
    get { return CatsConcat(); }
}
private System.Data.DataTable categories;
public System.Data.DataTable Categories 
{
	get { return categories; }
	set { categories = value; }
}
private string CatsConcat() {
	string result = "";
	foreach (System.Data.DataRow row in categories.Rows)
	{
		result += row["name"].ToString() + ", "; 
	}
	char[] c = {',', ' '};
	return result.TrimEnd(c).TrimStart(c);
}

vad tycks om det?

Medlem sedan maj 20012 812 inlägg
#6

Ja, jag har redan designat databasen på det sättet

Det gör det inte mer rätt!

vad tycks om det?

Inte alls.

Jag kan inte förstå varför du vill att din blogentry skall veta vilka kategorier den tillhör. Säg att du har 20 blogentrys i ditt minne, nu vill du visa alla blogentrys för kategorin: .NET hur plockar du då fram de blogentrys som tillhör kategorin: .NET?

- M

Medlem sedan nov. 20041 189 inlägg
#7

Det sköter en funktion i affärslagret. Hur menar du att man ska få fram vilka kategorier ett inlägg tillhör då? För det är ju det jag har frågat om hela tiden :l

Funktionen i affärslagret ser ut såhär:
public List<BlogEntry> GetAllEntries(string _sortExpression)

Så när jag binder till denna generic list med till exempel en ObjectDataSource så kan den automatiskt hämta vilka kategorier från varje instans av BlogEntry i BlogEntry-listan.

Medlem sedan maj 20012 812 inlägg
#8

public List<BlogEntry> GetAllEntries(string _sortExpression)

Vad är det för fel att så fall göra.
public List<BlogEntry> GetAllEntries(int categoryId)

Denna funktion går ner i databasen och hämtar upp alla blogentrys som har en relationt till dey kategoriid som du skickar med. På detta vis så behöver inte BlogEntry ha en anning om vilka kategorier den tillhör, den relationen finns i databasen.

- M

Medlem sedan nov. 20041 189 inlägg
#9

Men jag tror inte du förstår :s... Jag kan ju ha många olika kategorier för varje inlägg. Och sedan är det ju en motsägelse att kalla den funktionen som du skriver - GetAllEntries, då den bara hämtar vissa meddelanden. Och hur föreslår du att man ska visa alla inlägg på förstasidan då?

Jag frågar dig - vad är fel på det sättet jag har valt? Varför ska inte BlogEntry klassen veta vilka kategorier den tillhör? Det blir ju skitmycket enklare att binda en Repeater eller liknande till Listan då.

Jag har ju även en funktion i affärslagret som ser ut som den du precis skrev. Sedan har jag en för att hämta från en viss författare och en för att hämta alla inom ett datumintervall. Kolla på min screenshot!

Medlem sedan maj 20012 812 inlägg
#10

Jag kan ju ha många olika kategorier för varje inlägg.

Japp och det är inget problem, eftersom du vill hämta alla entries för en specific kategori, och den kategorin skickar du med in som en parameter till din funktion som hämtar alla entries som tillhör just den kategorin, det gör inget att de tillhör flera kategorier, det är du inte intresserad av att veta när du vill hämta alla entries för kategorin: .NET om en entry också tillhör kategorin: Architecture är ointressant när jag vill se alla entrys som tillhör: .NET.

Och sedan är det ju en motsägelse att kalla den funktionen som du skriver - GetAllEntries, då den bara hämtar vissa meddelanden.

Döp den till va fan du vill, det var ett exempel ta det för vad det är, kalla den nisse om du vill, det är jag ganska ointresserad av. Vilket gjorde att jag inte påpekade olämpligheten i namnet när du föreslog det.

Och hur föreslår du att man ska visa alla inlägg på förstasidan då?

Jag förslår inte att du visar alla inlägg på första sidan, utan kanske tar de 10 senaste helt oberoende av vilken kategori som de tillhör. Och för det så har du en method som heter: MinHund() som skickar tillbaka de 10 senaste entries.

Jag frågar dig - vad är fel på det sättet jag har valt? Varför ska inte BlogEntry klassen veta vilka kategorier den tillhör? Det blir ju skitmycket enklare att binda en Repeater eller liknande till Listan då.

Varför startade du tråden, för att allting var perfekt?
Jag kan dock inte riktigt se hur mycket enklare det blir att binda en lista med entites som har alla kategorier som en sträng arrays som en properties, än att binda en lista med entites som inte har en properties med alla kategorier som en properties, men det är ju bara jag...

Sedan har jag en för att hämta från en viss författare och en för att hämta alla inom ett datumintervall.

Perfekt, varför i hela världen vill du då inte ha en method som hämtar alla entries från en specifik kategori.

Det är möjligt att jag har missförstått vad du egentligen gör, men i min värld så verkar det som att du gör följande:

1. Hämtar ALLA entrys.
2. Väljer sedan att visa entrys för en specifik kategori
3. Du går du igen hela din lista och sorterar fram vilka entrys som matchar en specifik kategori utifrån en sträng array.

Om jag nu utmanar dig och säger att du har 2 miljoner entries i din databas, och 400 kategorier (helt provocerande tal). Och du bestämmer dig för att visa alla entries för din nya kategori: Magnus är bäst! Som innehåller 2 poster (så bra är jag :)) Så kanske du inser hur mycket datakraft som ligger på att sortera fram dessa 2 poster ur en lista som skall in och gör en massa sträng kontroller, istället för att låta en databas göra det den är bra på, hämta upp data.

Om du vill ha en array med alla kategorier i din blogentry så får du ha det, men det betyder inte att du skall använda dig av den informationen när du skall hämta ut entries från en specifik kategori, det är databasens jobb, eftersom du inte (hoppas jag iallfall) cachar all din data i ditt businesslager, det går bra att cacha delmängder, som exempel viss kategorier eftersom du vet att du inte kommer ha mer än 20-30 kategorier, och det tar inte speciellt mycket plats och du gör inga operationer på dem. Medans dina entrys kommer att växa med tiden, och skulle du råka skriva din caching rutin dåligt, så att varje användare får en egen cache, så får du problem med prestandan efter ett tag, då minne tar slut.

- M

Medlem sedan nov. 20041 189 inlägg
#11

Gladh skrev:

Döp den till va fan du vill, det var ett exempel ta det för vad det är, kalla den nisse om du vill, det är jag ganska ointresserad av. Vilket gjorde att jag inte påpekade olämpligheten i namnet när du föreslog det.

Hej igen! Är du verkligen glad(h) med tanke på dina insiktsfulla känsloyttringar??

Gladh skrev:

Jag förslår inte att du visar alla inlägg på första sidan, utan kanske tar de 10 senaste helt oberoende av vilken kategori som de tillhör. Och för det så har du en method som heter: MinHund() som skickar tillbaka de 10 senaste entries.

Ja, det är min "GetAllEntries(string _sortExpression)" som gör det.

Gladh skrev:

echoSwe skrev:

Jag frågar dig - vad är fel på det sättet jag har valt? Varför ska inte BlogEntry klassen veta vilka kategorier den tillhör? Det blir ju skitmycket enklare att binda en Repeater eller liknande till Listan då.

Varför startade du tråden, för att allting var perfekt?

Nej absolut inte - jag vill ha lite tips på hur jag skulle lösa problemet med att jag både använder class BlogEntry för att skicka med en instans av den för att lägga till ett nytt inlägg och för att binda en repeater till en List av densamme. Därför måste jag på något sätt få tag i vilka kategorier som inlägget tillhör och samtidigt kunna lägga in inlägget under rätt kategorier - så min undran var om jag har designat det hela fel i och med att mitt class BlogEntry måste ha både en public property med en sträng över kategorierna och en datatable - det verkar suboptimalt, men det är det smidigaste sättet som jag kommer på om man både ska kunna skicka en BlogEntry som parameter till en funktion för att lägga till i databasen som att binda en repeater med en collection av BlogEntry-s.

Jag förstår din ståndpunkt till fullo när det gäller att hämta inlägg - därför har jag två funktioner som heter GetAllEntries respektive GetEntriesByCategory (inte bara en alltså) och jag cachar inget ännu.

Dessutom: Vi lever inte i samma världar, då min värld säger att string _sortExpression inte handlar om kategorier - den handlar om att sortera efter datum, efter namn etc - därför implementerar den IComparer. En DataGrid kan nämligen skicka en parameter med den kolumn som innehållet ska sorteras efter och det är därifrån som jag ansåg att jag hade ett behov av _sortExpression. Så jag är helt med dig på punkten om att det är ineffektivt att först hämta alla inlägg och därefter sortera dem efter kategori.

Så min fråga är alltså hur man på bäst sätt gör att min repeater kan få tillgång till en concatenated stäng med kategorierna och hur jag samtidigt på ett smidigt sätt kan skicka en BlogEntry till en funktion i affärslagret som heter typ public string InsertEntry(BlogEntry e) { --- }.

Medlem sedan maj 20012 812 inlägg
#12

Jag förstår din ståndpunkt till fullo när det gäller att hämta inlägg - därför har jag två funktioner som heter GetAllEntries respektive GetEntriesByCategory (inte bara en alltså) och jag cachar inget ännu.

Bra! Då har jag missförstått vad dina funktioner gör.

Därför måste jag på något sätt få tag i vilka kategorier som inlägget tillhör och samtidigt kunna lägga in inlägget under rätt kategorier
...så min undran var om jag har designat det hela fel i och med att mitt class BlogEntry måste ha både en public property med en sträng över kategorierna och en datatable - det verkar suboptimalt...

Vill du göra båda dessa saker så måste du ha med informationen. En liten enklare variant hade så fall varit, att istället för att ha en property med en array av strängar och en datatable är att istället ha en property med som är en List<Category> eller bara din datatable av kategorier. På det sättet så har du bara en property som beskriver vilka kategorier som ditt entry tillhör, samt att du får med dig alla kategorier när du skickar ner det till ditt affärslager. Nackdelen blir att du i detta fall får skriva en mer komplicerad IComaper method själv när du vill sorterar på kategorier...

Hej igen! Är du verkligen glad(h) med tanke på dina insiktsfulla känsloyttringar??

Bara lackade ur på den tramsiga kommentaren om namnet på methoden, ungfär som om man bygger ett stortsystem till en kund och kommentaren man får från kunden när man visar alla coola finesser är: Måste bakgrunden vara vit, kan den inte vara blå? Precis om om det är för bakgrunden kunden lägger ner tusentals kronor...

- M

Medlem sedan nov. 20041 189 inlägg
#13

Okej, tack för din input Magnus. Om jag istället använder en List<Category> eller gör som jag har nu samt tar bort min publika metod

 public string Category
{
    get { return CatsConcat(); }
}

så måste jag ju (väl?) lägga till en funktion som varje gång sorterar och lägger samman kategorierna till en sträng när jag får upp min lista med BlogEntry-s i mitt presentationslager?

Medlem sedan maj 20012 812 inlägg
#14

så måste jag ju (väl?) lägga till en funktion som varje gång sorterar och lägger samman kategorierna till en sträng när jag får upp min lista med BlogEntry-s i mitt presentationslager?

Om du vill visa alla kategorier en entry hör till, så loopar du igenom listan av kategorier, om du väljer att skapa en property på blogentry som gör det till dig, eller väljer att göra det i koden där det behövs (codebehind) är upp till dig. Men på någotsätt så måste du ju få fram namnet på alla de kategorier som entityn är bunden till.

- M

276 ms totalt · 4 externa anrop · v20260731065814-full.86ec41c2
121 ms — deklarationer (db)
0 ms — hämta statistik (cache)
147 ms — hämta tråd, inlägg och bilagor (db)
125 ms — ändringar (db)