简体   繁体   中英

C# code optimization for accessing datatable records

i have a cost issue with datatable. And i need to replace the code with a smarter one.

i have a datatable and the sample values are like this:

Columns : id, user_id, starttime, endtime

Row Sample : 1 , 5, 05.10.2009 08:00:00,05.10.2009 17:00

my pseudo code is

    function something()
    {
    for(int i=0;i<datatable.Rows.Length;i++)
    {
    if(Someobject.variable.Equals(dt.Rows[i][user_id].ToString()))
    {
    if(Date.Compare(somevariable,dt.Rows[i][starttime].ToString())!=0)
    {
    //Do something
    }
    }
    }
}

it's something like that. The datatable has more than a thousand rows and the functions has to be called nearly a thousand times when the asp.net page loads.

So i have to change it.

i considered using dictionary but it seems that it takes only two variables. What can you suggest me.

Edit:

I could not solve the problem yet. Here is the related code. Thanks in advance.

protected void RadScheduler_Randevu_TimeSlotCreated(object sender, Telerik.Web.UI.TimeSlotCreatedEventArgs e) {

for (int i = 0; i < calismaSaatleridt.Rows.Count; i++)
{
    if (RadScheduler_Randevu.SelectedView.Equals(SchedulerViewType.DayView))
    {
        if (RadScheduler_Randevu.SelectedDate.ToShortDateString().Equals(Convert.ToDateTime(calismaSaatleridt.Rows[i]["calisma_baslangic"]).ToShortDateString()))
        {
            if (e.TimeSlot.Resource.Key.ToString().Equals(calismaSaatleridt.Rows[i]["hekim_id"].ToString()))
            {
                if (DateTime.Compare(e.TimeSlot.Start, Convert.ToDateTime(calismaSaatleridt.Rows[i]["calisma_baslangic"])) < 0 || DateTime.Compare(e.TimeSlot.End, Convert.ToDateTime(calismaSaatleridt.Rows[i]["calisma_bitis"])) > 0)
                {
                    e.TimeSlot.CssClass = "Disabled";
                }
            }
        }
    }
}

}

This is the function that returns the result set.

private DataTable calismaSaatiGetir(string yonetici_id)
    {
        SqlConnection connection = new SqlConnection();
        connection.ConnectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
        SqlCommand command = new SqlCommand();
        command.CommandText = "select calisma_saati.id,kullanici.id as hekim_id,LEFT(CONVERT(VARCHAR,calisma_saati.tarih,104),10)+ ' ' +LEFT(CONVERT(VARCHAR,calisma_saati.baslangic_saati,108),5) AS calisma_baslangic,LEFT(CONVERT(VARCHAR,calisma_saati.tarih,104),10)+ ' '+LEFT(CONVERT(VARCHAR,calisma_saati.bitis_saati,108),5) AS calisma_bitis from calisma_saati JOIN kullanici ON kullanici.id=calisma_saati.kullanici_id WHERE  yonetici_id='" +  Session["yonetici"].ToString() + "' ";
        command.Connection = connection;
        connection.Open();
        SqlDataAdapter da = new SqlDataAdapter(command.CommandText, connection);
        DataSet ds = new DataSet();
        da.Fill(ds, "calisma_saati");
        calismaSaatleridt = ds.Tables["calisma_saati"];
        connection.Close(); 
        return calismaSaatleridt;
    }

The datatable has more than a thousand rows and the functions has to be called nearly a thousand times

There's your problem. If I'm reading that right, you're looping through the entire datatable for every item in some other collection of data that isn't shown in the question.

The best way to fix this is at the database level: whatever you're doing to generate this datatable needs to know about your other data set so you can take it into account on the database (and make use of things like indexes and cached data). That might mean writing a select query that is much more complicated than what you're used to, but it's the right way to do this.

If this just isn't an option, you still want to re-work this in some way so that you only interate through everything once. If you're using c#, you can probably accomplish that via a linq query (or even just the IEnumerable extensions + lambda methods).

Regarding using a dictionary: it may take only two variables, but one of those variables could be a more-complicated object, like an entire datarow from your table. Either way, to give you anything like sample code we need a better idea of what that other data looks like and what your intended result is.

Is this coming from a database directly? If so, why not just perform a query to get a more specific result set? Then you could use linq to get execute your function on each row.

More defined SQL: select * from table where userID = 'bob' and starttime between '1/1/2009 11:00 PM' and '1/1/2009 11:21 PM'

Linq:

DataTable table = getFromDb();
table.Rows.Cast<DataRow>().ToList().ForEach(x => RunMyFunction(x));

void RunMyFunction(DataRow row)
{

}

how about this? (it would be better if you could push this query to the database. but this will be faster than looping every row)

void something(DataTable dt, myobj Someobject, DateTime somevariable)
{
    string filterPattern = "user_id='{0}' AND starttime='{1}'";
    string filter = string.Format(filterPattern, 
                                  Someobject.variable, 
                                  somevariable);
    DataRow[] rows = dt.Select(filter);

    foreach (DataRow row in rows)
        DoSomething(row);
}
void DoSomething(DataRow row)
{
}
public class myobj
{
    public string variable { get; set; }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM