View Full Version : MaxDate And Min Date َ و حذف گروهی
  
پرستو پارسایی
چهارشنبه 20 آذر 1398, 14:39 عصر
سلام 
1 -نحوه بدست آوردن کوچکترین تاریخ شمسی و بزرگترین تاریخ شمسی لود شده در دیتا گرید رو میخوام بدونم . فرمت ( 1398/06/22)
2 -چه جوری میتونم تاریخ های که تو دیتا گرید فیلتر کردم رو یکجا حذف کنم. مثلا تعداد زیادی رکورد دارم و وقتی فیلتر میکنم 15 رکود نمایش داده میشه . این 15 رکورد رو چه جوری یکجا از دیتابسیم (SQL) حذف کنم
ممنون میشم در صورت اطلاع پاسخ دهید
پرستو پارسایی
پنج شنبه 21 آذر 1398, 13:10 عصر
سلام وجدد به دوستان 
با این کد  minDate  و   maxDate  رو از دیتا گرید لود کردم
ولی بخش دوم سوالم رو درمورد حذف چند رکورد همزمان رو موفق نبودم ممنون میشم دوستان اگر اطلاع دارید پاسخ دهید  سپاس
 Private Structure cell 
       Dim rowIndex As Integer
        Dim columnIndex As Integer
    End Structure
'''''''''''''''''''''''''''''''''''''''''''''''''' '''''''''''''''Event Btn''''''''''''''''''''''''''''''''''''''''''''''' '''''''''''  
    Dim cells = From r As DataGridViewRow In DataGridView1.Rows.Cast(Of DataGridViewRow)() _
                Where Not r.IsNewRow _
                Select CStr(r.Cells(1).Value)
        Dim min As String = cells.Min
        Dim minAddress As New cell With {.columnIndex = 0, .rowIndex = Array.IndexOf(cells.ToArray, min)}
        Dim max As String = cells.Max
        Dim maxAddress As New cell With {.columnIndex = 0, .rowIndex = Array.IndexOf(cells.ToArray, max)}
        TextBox1.Text = min
        TextBox2.Text = max
the king
پنج شنبه 21 آذر 1398, 19:45 عصر
سلام 
1 -نحوه بدست آوردن کوچکترین تاریخ شمسی و بزرگترین تاریخ شمسی لود شده در دیتا گرید رو میخوام بدونم . فرمت ( 1398/06/22)
        With DataGridView1.Rows
            If .Count > 0 Then
                Dim minDate As String = .Item(0).Cells.Item("Date").Value
                Dim maxDate As String = minDate
                For i = 1 To .Count - 1
                    Dim d As String = .Item(i).Cells.Item("Date").Value
                    If d Is Nothing OrElse d.Length <> 10 Then Continue For
                    If minDate > d Then minDate = d
                    If maxDate < d Then maxDate = d
                Next
                TextBox1.Text = minDate
                TextBox2.Text = maxDate
            End If
        End With
2 -چه جوری میتونم تاریخ های که تو دیتا گرید فیلتر کردم رو یکجا حذف کنم. مثلا تعداد زیادی رکورد دارم و وقتی فیلتر میکنم 15 رکود نمایش داده میشه . این 15 رکورد رو چه جوری یکجا از دیتابسیم (SQL) حذف کنم
ممنون میشم در صورت اطلاع پاسخ دهید
اگر بخواهید یک رکورد رو بر اساس سطر در DataGridView حذف کنید بهتره که کلید اون رکورد رو هم در ستون ها داشته باشید. حتی میتونه اون ستون مخفی از دید کاربر باشه ولی به هر حال برای حذف کردن دقیق به Id یا کلید رکورد نیاز هست.
        DataGridView1.Columns.Item("Id").Visible = False
        With DataGridView1
            If .Rows.Count > 0 Then
                Using connection As New SqlConnection(connectionString)
                    connection.Open()
                    Using command As New SqlCommand("DELETE FROM [YourTable] WHERE [Id] IN (", connection)
                        Dim pList As New List(Of String)
                        For i = 0 To .Rows.Count - 1
                            If .Rows.Item(i).Cells.Item("Id").Value Is Nothing Then Continue For
                            pList.Add("@p" + i.ToString())
                            command.Parameters.AddWithValue("@p" + i.ToString(), .Rows.Item(i).Cells.Item("Id").Value)
                        Next
                        command.CommandText += String.Join(",", pList.ToArray()) + ");"
                        command.ExecuteNonQuery()
                    End Using
                End Using
            End If
            .DataSource = Nothing
            .Rows.Clear()
        End With
پرستو پارسایی
پنج شنبه 21 آذر 1398, 22:20 عصر
سلام ممنونم از پاسختان باز هم یک پاسخ عالی (سپاس)
mazoolagh
شنبه 23 آذر 1398, 10:47 صبح
چند سئوال برای من پیش آمده که با اجازه یکی یکی مطرح میکنم:
1- کدی که استارتر تاپیک در پست 2 گذاشته بودن درست بود (هر چند که ساده تر میشه نوشت)، چرا باید حلقه بگذاریم برای پیدا کردن min / max ؟
        dim dates=from row as datagridviewrow in DataGridView1.rows where row.cells("date").value isnot nothing select row.cells("date").value
        if dates.count > 0 then
            TextBox1.Text=dates.min()
            TextBox2.Text=dates.max()
        end if
mazoolagh
شنبه 23 آذر 1398, 10:53 صبح
2- برای پیدا کردن min/max میشه مستقیم از compute برای datatable هم استفاده کرد:
        dim dt as datatable=DataGridView1.datasource.defaultview.tot able
        TextBox1.Text=dt.compute("min(date)","")
        TextBox2.Text=dt.compute("max(date)","")
و باز هم نیازی به حلقه نیست
mazoolagh
شنبه 23 آذر 1398, 11:12 صبح
3- برای ساختن لیست ID ها و گذاشتن اون در commandtext هم باز نیازی به حلقه نیست:
        dim ids=from row as datagridviewrow in DataGridView1.rows where row.cells("id").value isnot nothing select row.cells("id").value
        With DataGridView1
            Using connection As New SqlConnection(connectionString)
                connection.Open()
                Using command As New SqlCommand
                    command.CommandText = "DELETE FROM [YourTable] WHERE [Id] IN (@ids)".replace("@ids",join(ids.toarray,","))
                    command.ExecuteNonQuery()
                End Using
            End Using
            .DataSource = Nothing
            .Rows.Clear()
        End With
پرستو پارسایی
شنبه 23 آذر 1398, 13:18 عصر
ممنونم از توجه شما کد شما خیلی کمک کرد سپاس
the king
شنبه 23 آذر 1398, 19:52 عصر
چند سئوال برای من پیش آمده که با اجازه یکی یکی مطرح میکنم:
1- کدی که استارتر تاپیک در پست 2 گذاشته بودن درست بود (هر چند که ساده تر میشه نوشت)، چرا باید حلقه بگذاریم برای پیدا کردن min / max ؟
        dim dates=from row as datagridviewrow in DataGridView1.rows where row.cells("date").value isnot nothing select row.cells("date").value
        if dates.count > 0 then
            TextBox1.Text=dates.min()
            TextBox2.Text=dates.max()
        end if
سوال خیلی خوبی است. حلقه یا Linq یا هر روش دیگری که برای حل مساله بکار می بریم نیاز ما نیستند، نیاز ما حل مساله است که برای حل کردنش هم گزینه های مختلفی داریم.
 اون چیزی که در انتخاب بین این گزینه ها کمک می کنه مقایسه روش ها است، پیچیدگی زمانی شون، زمان لازم برای نوشتن شون، زمان اجراشون، خوانایی کد شون و ...
متاسفانه همیشه نمیشه همه پارامتر ها رو در حد مطلوب نگهداشت، مثلا کدی که شما نوشتید از نظر تعداد سطر کد خیلی خوبه، اما زمان لازم برای اجراش به مراتب کند تر از اون کد طولانی تری است که من با حلقه for نوشتم :
    Private _dg As New DataGridView
    Private _lst As New ListBox
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim source As New DataTable
        _lst.Parent = Me
        _lst.Dock = DockStyle.Fill
        source.Columns.Add("Date")
        Dim rnd As New Random
        For i = 0 To 100000
            Dim row As DataRow = source.NewRow
            row("Date") = $"{rnd.Next(1300, 1400)}/{rnd.Next(1, 12)}/{rnd.Next(1, 30)}"
            source.Rows.Add(row)
        Next
        _dg.DataSource = source
        _dg.Parent = Me
        _dg.Dock = DockStyle.Right
    End Sub
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim elapsed As Long
        Button1.Enabled = False
        _lst.Items.Add("please wait...")
        Application.DoEvents()
        _lst.Items.Add("Method1...")
        Dim sw As New Stopwatch
        sw.Start()
        Dim dates = From row As DataGridViewRow In _dg.Rows Where row.Cells("date").Value IsNot Nothing Select row.Cells("date").Value
        If dates.Count > 0 Then
            TextBox1.Text = dates.Min()
            TextBox2.Text = dates.Max()
        End If
        sw.Stop()
        elapsed = sw.ElapsedTicks
        _lst.Items.Add("Elapsed (ticks): " & sw.ElapsedTicks)
        sw.Reset()
        _lst.Items.Add("Method2...")
        Application.DoEvents()
        sw.Start()
        With _dg.Rows
            If .Count > 0 Then
                Dim minDate As String = .Item(0).Cells.Item("Date").Value
                Dim maxDate As String = minDate
                For i = 1 To .Count - 1
                    Dim d As String = .Item(i).Cells.Item("Date").Value
                    If d Is Nothing OrElse d.Length <> 10 Then Continue For
                    If minDate > d Then minDate = d
                    If maxDate < d Then maxDate = d
                Next
                TextBox1.Text = minDate
                TextBox2.Text = maxDate
            End If
        End With
        sw.Stop()
        _lst.Items.Add("Elapsed (ticks): " & sw.ElapsedTicks)
        _lst.Items.Add($"Method 1 is {((elapsed - sw.ElapsedTicks) / sw.ElapsedTicks):0.0} times slower.")
        Button1.Enabled = True
    End Sub
من اگه از حلقه for استفاده کردم نه به این خاطر بود که Linq رو نمیشناسم. نه علاقه خاصی به for دارم و نه Linq
دقیقا به این خاطر بود که Linq رو میشناختم، میدونستم که استفاده ازش با وجود کاهش حجم کد نویسی چقدر کارایی در اجرا رو پایین میاره.
از روی ظاهر کدها نمیشه قضاوت کرد، مثل تفاوت ظاهری کد الگوریتم های مرتب سازی حبابی و مرتب سازی سریع
the king
شنبه 23 آذر 1398, 19:57 عصر
2- برای پیدا کردن min/max میشه مستقیم از compute برای datatable هم استفاده کرد:
        dim dt as datatable=DataGridView1.datasource.defaultview.tot able
        TextBox1.Text=dt.compute("min(date)","")
        TextBox2.Text=dt.compute("max(date)","")
و باز هم نیازی به حلقه نیست
حلقه نیاز ما نیست، همونطور که کند شدن کد هم نیاز ما نیست. ما کدی رو انتخاب میکنیم که کارایی بهتری ایجاد کنه، مگر اینکه بخواهیم به دلیل خاصی ازش اجتناب کنیم.
چه نیازی داریم که کدی بنویسیم که چند برابر کند بشه؟ صرفا برای اینکه حلقه نداشته باشه؟ حلقه داشتن و نداشتن به خودی خود هیچ ارزش یا عیبی محسوب نمیشه.
    Private _dg As New DataGridView
    Private _lst As New ListBox
    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        Dim elapsed As Long
        Button2.Enabled = False
        _lst.Items.Add("please wait...")
        Application.DoEvents()
        _lst.Items.Add("Method1...")
        Dim sw As New Stopwatch
        sw.Start()
        Dim dt As DataTable = _dg.DataSource.DefaultView.ToTable
        TextBox1.Text = dt.Compute("min(date)", "")
        TextBox2.Text = dt.Compute("max(date)", "")
        sw.Stop()
        elapsed = sw.ElapsedTicks
        _lst.Items.Add("Elapsed (ticks): " & sw.ElapsedTicks)
        sw.Reset()
        _lst.Items.Add("Method2...")
        Application.DoEvents()
        sw.Start()
        With _dg.Rows
            If .Count > 0 Then
                Dim minDate As String = .Item(0).Cells.Item("Date").Value
                Dim maxDate As String = minDate
                For i = 1 To .Count - 1
                    Dim d As String = .Item(i).Cells.Item("Date").Value
                    If d Is Nothing OrElse d.Length <> 10 Then Continue For
                    If minDate > d Then minDate = d
                    If maxDate < d Then maxDate = d
                Next
                TextBox1.Text = minDate
                TextBox2.Text = maxDate
            End If
        End With
        sw.Stop()
        _lst.Items.Add("Elapsed (ticks): " & sw.ElapsedTicks)
        _lst.Items.Add($"Method 1 is {((elapsed - sw.ElapsedTicks) / sw.ElapsedTicks):0.0} times slower.")
        Button2.Enabled = True
    End Sub
the king
شنبه 23 آذر 1398, 20:03 عصر
3- برای ساختن لیست ID ها و گذاشتن اون در commandtext هم باز نیازی به حلقه نیست:
        dim ids=from row as datagridviewrow in DataGridView1.rows where row.cells("id").value isnot nothing select row.cells("id").value
        With DataGridView1
            Using connection As New SqlConnection(connectionString)
                connection.Open()
                Using command As New SqlCommand
                    command.CommandText = "DELETE FROM [YourTable] WHERE [Id] IN (@ids)".replace("@ids",join(ids.toarray,","))
                    command.ExecuteNonQuery()
                End Using
            End Using
            .DataSource = Nothing
            .Rows.Clear()
        End With
مثالی که زدید ظاهر خوبی داره. اما یک ایراد بزرگ هم داره. مستعد SQL Injection ئه. 
اگر کاربر ستون id رو ببینه و بتونه داحلش مقدار دلخواهش رو وارد کنه میتونه کد SQL ای رو اجرا کنه که مطلوب نیست. انتخاب Parameters بخاطر همینه که از SQL Injection جلوگیری بشه.
پرستو پارسایی
یک شنبه 24 آذر 1398, 12:28 عصر
ممنونم از پاسختان بسیار آموزنده بود . من فکر میکردم کد نویسی بخش بزرگیش مثل امضاء برنامه نویسش هست چون به چندین روش انجام میشه ولی با این توضیحات نظرم تغییر کرد .
الان متوجه شدم برای نوشتن یک کد فقط نیاید به انجام دادن  Event  اون قطعه کد فکر کرد ، بلکه میبایست سایر پارامترها رو هم برای بهبودکیفیت در نظر گرفت.
به هر حال من فکر میکنم هدف مدیران محترم سایت (بخش آموزش) هست و دوستان همه تلاش میکنند تا بهم کمک کنن .
من مجددا از پاسخگویی دوستان بخاطر به اشتراک گذاشتن اطلاعات با ارزششان کمال تشکر را دارم .
mazoolagh
دوشنبه 25 آذر 1398, 14:22 عصر
@the king
قبل از هر چیز باید تشکر کنم از این که با حوصله و دقیق پاسخ میدین، 
و خوشحالم که متوجه هستین که هدف از این پرسشها هم صرفا یادگیری و دونستن چراها هست.
و همچنین تشکر از استارتر تاپیک که بانی خیر شدن.
نمیدونم وقت و حوصله دارین یا نه، ولی هنوز چند مورد هست (هم در زمینه همین ها که مطرح شد و هم نکات دیگه) که اگر اجازه بدین در همین تاپیک بپرسم.
==========
خارج از موضوع : به اختلاف نظر اهل فن درباره روش های سورت اشاره کردین و همچنین پرفورمنس برنامه؛ شاید جالب باشه بدونین که اون قدیما که دیتا روی کارت های موسوم به هالریت پانچ میشد وقت سیستم بطور کلی و وقت پردازشگر بطور خاص اونقدر مهم بود که دیتا رو قبل از پردازش اول با یک دستگاه مکانیکی سورت میکردن!
تقریبا تمام سایت های کامپیوتری حداقل یک دستگاه IBM 084 داشتن که از نظر فنی و پیچیدگی شاهکاری بود برای خودش و راحت 30-40 کارت (رکورد) رو میتونست در ثانیه سورت کنه.
the king
دوشنبه 25 آذر 1398, 16:14 عصر
@the king
قبل از هر چیز باید تشکر کنم از این که با حوصله و دقیق پاسخ میدین، 
و خوشحالم که متوجه هستین که هدف از این پرسشها هم صرفا یادگیری و دونستن چراها هست.
و همچنین تشکر از استارتر تاپیک که بانی خیر شدن.
نمیدونم وقت و حوصله دارین یا نه، ولی هنوز چند مورد هست (هم در زمینه همین ها که مطرح شد و هم نکات دیگه) که اگر اجازه بدین در همین تاپیک بپرسم.
 
من از شما ممنونم که در مباحث شرکت می کنید.
معلوماتم زیاد نیست ولی حوصله ام چرا. اگه مباحث به کسی کمکی بکنه خوشحال میشم در اونها مشارکت داشته باشم.
خارج از موضوع : به اختلاف نظر اهل فن درباره روش های سورت اشاره کردین و  همچنین پرفورمنس برنامه؛ شاید جالب باشه بدونین که اون قدیما که دیتا روی  کارت های موسوم به هالریت پانچ میشد وقت سیستم بطور کلی و وقت پردازشگر  بطور خاص اونقدر مهم بود که دیتا رو قبل از پردازش اول با یک دستگاه  مکانیکی سورت میکردن!
تقریبا تمام سایت های کامپیوتری حداقل یک دستگاه IBM 084 داشتن که از نظر  فنی و پیچیدگی شاهکاری بود برای خودش و راحت 30-40 کارت (رکورد) رو میتونست  در ثانیه سورت کنه.
کارت های پانج شده رو یادم میاد، خواهرم در دانشگاه ازشون استفاده میکرد. دانشجو ها باید کارت ها رو پانچ شده و شماره گذاری شده تحویل سایت میدادن و فردا پسفردا میومدن نتیجه رو تحویل بگیرن که ببینن آیا اشتباهی داشتن یا نه.
حالا مصبت کار با اون IBM 084 به کنار، لااقل ابعادش منطقی بود. پدرم تعریف کرده بود که وقتی برای سازمان آب منطقه ای کامپیوتر آوردن یک هیولایی بود اندازه یک اتاق بزرگ که خودش باید در یک سالن بزرگ با شرایط دما و رطوبت خاصی جای میگرفت.
 
vBulletin® v4.2.5, Copyright ©2000-1404, Jelsoft Enterprises Ltd.