Avatar billede baitianlong Nybegynder
14. november 2010 - 05:57 Der er 5 kommentarer og
1 løsning

Kan dette goeres nemmere?

Jeg har et felt i en SqlServer tabel, som hedder "friends". Strukturen er saadan her:

23423|534534|345|2423|5656|4564

Userids splittet med pipe.

Naar jeg vil tilfoeje en ny ven, skal min metode putte den nye ind foerst, saadan her:

NYVENID|23423|534534|345|2423|5656|4564

Jeg har lavet en metode, som foerst henter strengen, derefter laegger den nye streng foerst og derefter tager de 99 naeste, saaledes at der altid kun er max 100. Metoden ser saadan her ud:

public int AddToFriends(int userid, int friendid)
    {
        int result = 0;
        string sql1 = "SELECT friends FROM lfstats WHERE userid=@userid";
        string currentfriends, newfriends;
        try
        {
            using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["lfcs"].ToString()))
            using (SqlCommand cmd = new SqlCommand(sql1))
            {
                con.Open();
                cmd.Connection = con;
                cmd.CommandType = CommandType.Text;
                using (SqlDataReader rdr = cmd.ExecuteReader())
                {
                    if (rdr.Read())
                        currentfriends = rdr["friends"].ToString();
                }
            }
        }
        catch (SqlException e)
        {
            throw e;
        }
        int[] friendsarr = currentfriends.Split(new char[] { '|' });
        newfriends = friendid.ToString();
        int i = 0;
        while (i < friendsarr.Length)
        {
            if (i < 99)
            {
                newfriends += "|" + friendsarr[i];
            }
            i++;
        }
        string sql2 = "UPDATE lfstats SET friends=@newfriends WHERE userid=@userid";
        string sql3 = "DELETE FROM lfpendingfriend WHERE fromid=@friendid AND toid=@userid";
        try
        {
            using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["lfcs"].ToString()))
            using (SqlCommand cmd = new SqlCommand(sql2))
            {
                con.Open();
                cmd.Connection = con;
                cmd.CommandType = CommandType.Text;
                cmd.Parameters.Add("@newfriends", SqlDbType.NVarChar).Value = newfriends;
                result = cmd.ExecuteNonQuery();
                cmd.CommandText = sql3;
                cmd.Parameters.Add("@friendid", SqlDbType.Int).Value = friendid;
                cmd.Parameters.Add("@userid", SqlDbType.Int).Value = userid;
                result = cmd.ExecuteNonQuery();
            }
        }
        catch (SqlException e)
        {
            throw e;
        }
        return result;
    }

Som det ses er der 3 sql statements, 2 sqlconnections og hvad ved jeg :) Kan jeg ikke goere dette nemmere (og hurtigere), maaske med bedre SQL statements?
Avatar billede bvli Praktikant
14. november 2010 - 06:45 #1
Jeg tror reelt at databasen er bedre end dig til at håndtere relationer. Og den måde du prøver at relatere en friend til en user er ikke den bedste måde at gøre det på.

Hvis du insisterer, så brug i det mindste string.Join("|"friendsarr) til at lave din string.

Men det bedste ville nok være at lave en ny tabel:

UserId | FriendId | DateAdded


Og så hver gang din user får en ny ven, så
INSERT INTO UserFriends values (UserId, FriendId, DateAdded)

Og når du skal hente din users friends:

select FriendId from UserFriends where userId = @userId order by DateAdded desc
Avatar billede baitianlong Nybegynder
14. november 2010 - 08:09 #2
Ja det giver jo mening og goer det hele lidt lettere med en tabel mere ;) Ved ikke hvorfor jeg ville have den streng. Du kan bare svare :) Men nu hvor jeg har dig; kan man fyre 2 eller flere sql statements af paa een gang (i een commandtext), saaledes at:

using (SqlCommand cmd = new SqlCommand(sql2))
            {
                con.Open();
                cmd.Connection = con;
                cmd.CommandType = CommandType.Text;
                cmd.Parameters.Add("@newfriends", SqlDbType.NVarChar).Value = newfriends;
                result = cmd.ExecuteNonQuery();
                cmd.CommandText = sql3;
                cmd.Parameters.Add("@friendid", SqlDbType.Int).Value = friendid;
                cmd.Parameters.Add("@userid", SqlDbType.Int).Value = userid;
                result = cmd.ExecuteNonQuery();
            }

kunne blive til (blot et eksempel):

using (SqlCommand cmd = new SqlCommand(sql2 + "; " + sql3))
            {
                con.Open();
                cmd.Connection = con;
                cmd.CommandType = CommandType.Text;
                cmd.Parameters.Add("@newfriends", SqlDbType.NVarChar).Value = newfriends;
                cmd.Parameters.Add("@friendid", SqlDbType.Int).Value = friendid;
                cmd.Parameters.Add("@userid", SqlDbType.Int).Value = userid;
                result = cmd.ExecuteNonQuery();
            }

Saa ville den vel returnere resultatet fra sql3??
Avatar billede bkp Nybegynder
15. november 2010 - 07:56 #3
Du kan kun fyre 1 statement af pr. kald, men du kan jo bare kalde den flere gange med samme connection, hvilket vil køre bedre end at oprette connection 2 eller 3 gange.

Men lige en advarsel, du skal ikke dermed tro at jeg mener din connection skal forblive åben, man skal altid lukke den pænt igen når du er færdig.
Avatar billede Syska Mester
15. november 2010 - 09:05 #4
Ja, da .NET bruger Connection Pooling ( Tror jeg nok de kalder det )

Men derfor kan du vist stadig BATCH dine update.

UPDATE Table SET Bla = 'Blu' WHERE Id = 10;
UPDATE Table SET Bla = 'Blu' WHERE Id = 10;
UPDATE Table SET Bla = 'Blu' WHERE Id = 10;

eller

UPDATE Table SET Bla = 'Blu' WHERE Id = 10;
GO
UPDATE Table SET Bla = 'Blu' WHERE Id = 10;
GO
UPDATE Table SET Bla = 'Blu' WHERE Id = 10;

Og så have det som command tekst.

Ikke testet ... da det er utroligt lidt man vinder ved det, men Ayende gør det i NHibernate med Futures.

mvh
Avatar billede bvli Praktikant
15. november 2010 - 18:35 #6
Hep
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester