PDA

View Full Version : وارد کردن حجم زیادی از اطلاعات به دیتابیس



saeidcd
دوشنبه 16 فروردین 1389, 11:47 صبح
سلام به همه من یه موتور دارم که باید حجم زیادی از اطلاعات رو یکجا تو دیتابیس بریزه من برای اینکار از یه حلقه استفاده کردم اما چون حجمش اطلاعات ورودی و تعدادش زیاده برنامه وسط اجرا به من خطا میده(که عکسش رو هم براتون ضمیمه کردم) چطور میتونم سربار خوندن و اظافه کردن اطلاعات رو از دیتابیس کم کنم تا حلقه زودتر تموم بشه و برنامه بتونه کار خودش رو تموم کنه مثلا باید تو یه حلقه 1000 تا رکورد رو وارد کنم یا جستجو کنم که قبلا وارد شده یا نه البته من مجبورم بعد از وارد کردن اطلاعات یا خوندن اطلاعات کانکشن رو ببندم و دوباره وصل بشم ایا راهی هست که من مجبور نباشم هر دفعه کانکشن رو قطع و وصل کنم

majid325
سه شنبه 17 فروردین 1389, 13:45 عصر
شما بگین چند تا رکورد باید وارد شود حدودی؟
چه مسائلی باید چک شود؟

از چه منبعی اطلاعات رو میخونین؟(text,sql,access)
تو چه منبعی میخواین بریزین؟

نمونه کدی که الان استفاده میکنی؟

saeidcd
سه شنبه 17 فروردین 1389, 16:17 عصر
از توجهتون ممنون
من حدود 500 تا رکورد دارم باید اول چک بشه که تو دیتابیس وجود داره یا نه- اگه وجود داشت ای دی اون رو به ما بده تا تو table2 بریزم -اگه وجود نداشت اون رو اظافه کنه بعد ای دی اون رو به من بده و در اخر هم اون رو تو table2 بریزه
منبع خوندن اطلاعات از کدهای html صفحات webbrowser هست یعنی دارم از خودم برنامه اون رو میخونم
باید تو دیتابیس sql بریزم
قسمت اصلی کد هم اینه



Private Sub savedb()
Dim sqlreader As String = "select url,id from url where url=@url "

Dim sqlinsert As String = "insert url ( url ) values ( @url )"

Dim sqlreaderinsert As String = "insert link ( mabda , maghsad ) values ( @mabda , @maghsad )"

Dim sqlupdate As String = "update url set vaziat='1' , title=@title where id=@id"

Dim i As Integer = 0
'link(i) شامل مواردی هستش که باید چک بشه
While link(i) Is Nothing = False

If cn.State = ConnectionState.Open Then cn.Close()
cn.Open()

Dim com As SqlCommand = New SqlCommand(sqlreader, cn)
com.Parameters.AddWithValue("@url", link(i))

Dim reader As SqlDataReader = com.ExecuteReader()

reader.Read()

اگه توی دیتابیس وجود داشت
If reader.HasRows Then
ای دی اون رو بگیر
natijecount = reader.GetInt64(1)
reader.Close()

GoTo addi

Else
وگرنه اون رو به دیتابیس اضافه کن
If cn.State = ConnectionState.Open Then cn.Close()
cn.Open()
Dim Comm As SqlCommand = New SqlCommand(sqlinsert, cn)
Comm.Parameters.AddWithValue("@url", link(i))
'
Comm.ExecuteNonQuery()


If cn.State = ConnectionState.Open Then cn.Close()
cn.Open()
Dim com3 As SqlCommand = New SqlCommand(sqlreader, cn)
com3.Parameters.AddWithValue("@url", link(i))

reader.Close()

Dim reader1 As SqlDataReader = com3.ExecuteReader()
reader1.Read()

ای دی چیزی رو که اضافه کردی بده
If reader1.HasRows Then
natijecount = reader1.GetInt64(1)
End If

End If

addi:

در هر صورت اونها رو به این جدول اضافه کن
'mabda=link safhe asli
'maghsad=link haie dar safhe asli
If cn.State = ConnectionState.Open Then cn.Close()
cn.Open()
Dim com2 As SqlCommand = New SqlCommand(sqlreaderinsert, cn)
com2.Parameters.AddWithValue("@mabda", natijecount)
com2.Parameters.AddWithValue("@maghsad", natijeid)

com2.ExecuteNonQuery()

i += 1
End While




'********* دیتابیس رو اپدیت کن که بدونم این 500 رکورد چک شده و دوباره چک نشه
title = WebBrowser1.Document.Title
If cn.State = ConnectionState.Open Then cn.Close()
cn.Open()
Dim comm2 As SqlCommand = New SqlCommand(sqlupdate, cn)
comm2.Parameters.AddWithValue("@id", natijeid)
comm2.Parameters.AddWithValue("@title", title)

comm2.ExecuteNonQuery()
end subحدود 500 رکورد هر دفعه باید چک بشه وقتی به نصف این تعداد میرسه برنامه خطا میده که باید continue رو بزنم تا ادامه پیدا کنه

majid325
چهارشنبه 18 فروردین 1389, 01:10 صبح
کدتون خیلی رسا نیست ، احتمال داره از حلقه بیرون نیاد در شرایطی ؟

saeidcd
چهارشنبه 18 فروردین 1389, 10:44 صبح
:قلب::قلب::قلب:


نه ببینید توی حلقه با مشکل مواجه میشم وقتی مثلا قراره 500 رکورد چک بشه وقتی به رکورد 300 میرسه باید به خطا پاسخ بدم بعد از اون 200 تای بقیه چک میشه و برنامه کار خودش رو انجام میده مسیلهای که هست اینه که این حلقه خیلی کند اجرا میشه اگه لطف کنید بگید که راهی هست که این حلقه سریعتر انجام بشه یا کدهاش بهتر بشه

توی کد توضیحاتی رو اضافه کردم لطف کن یه نگاه دیگه بنداز

majid325
پنج شنبه 19 فروردین 1389, 02:19 صبح
1-تو همچین حلقه های نباید یک آبجکت رو new کرد :
هر آبجکتی که new کردین رو قبل از حلقه تعریف و در صورت نیاز از متد مربوطه شان برای reSet شدن مقادیر استفاده کنید
2-بهتره قبل از حلقه کانکشن رو باز و بعد از حلقه ببندید
3-در جاهای که به یک مقدار (Scalar value) نیاز دارین , نیاز نیست از data reader استفاده کنید ، با کمی تغییر در کوئریتون میتونید از همون متد ExecuteScalar کامند مربوطه استفاده کنید
4- اگر اون GoTo addi رو بردارین هیچ تغییری در منطق نمی افته و کمی هم سرعت بیشتر میشه

saeidcd
پنج شنبه 19 فروردین 1389, 10:58 صبح
کارهایی که گفته بودید انجام دادم (به غیر از ExecuteScalar چون تا حالا باهاش کار نکردم و نمیدونستم چه مواقعی باید ازش استفاده کرد)برنامه خیلی خواناتر و بهتر شد
اما عجیب اینکه سرعت اجرای حلقه کمتر شد و اگه قبلا از 500 رکورد وقتی به 250 میرسید خطا میداد حالا وقتی به 150 میرسه با خطا مواجه میشم :عصبانی++:




If cn.State = ConnectionState.Open Then cn.Close()
cn.Open()

While link(i) Is Nothing = False

com.CommandText = sqlreader
com.Connection = cn
com.Parameters.AddWithValue("@url", link(i))

Dim reader As SqlDataReader = com.ExecuteReader()

reader.Read()

If reader.HasRows Then

natijecount = reader.GetInt64(1)
reader.Close()

Else

com.CommandText = sqlinsert
com.Connection = cn
com.Parameters.Clear()
com.Parameters.AddWithValue("@url", link(i))

com.ExecuteNonQuery()

com.CommandText = sqlreader
com.Connection = cn

com.Parameters.Clear()

com.Parameters.AddWithValue("@url", link(i))

reader.Close()

Dim reader1 As SqlDataReader = com.ExecuteReader()
reader1.Read()
If reader1.HasRows Then
natijecount = reader1.GetInt64(1)
End If

End If

com.Connection = cn
com.CommandText = sqlreaderinsert
com.Parameters.Clear()
com.Parameters.AddWithValue("@mabda", natijecount)
com.Parameters.AddWithValue("@maghsad", natijeid)

com.ExecuteNonQuery()

i += 1
End While


'*********
title = WebBrowser1.Document.Title
com.CommandText = sqlupdate
com.Connection = cn
com.Parameters.Clear()
com.Parameters.AddWithValue("@id", natijeid)
com.Parameters.AddWithValue("@title", title)

com.ExecuteNonQuery()

FastCode
پنج شنبه 19 فروردین 1389, 14:34 عصر
باید بین هر 20 تا 30 تا insert یک بار application.DoEvents رو کال کنید تا کارتون راه بیافته.یا از یه ترد دیگه استفاده کنید.

saeidcd
پنج شنبه 19 فروردین 1389, 16:16 عصر
از توجهتون ممنون
ببخشید منظورتون رو درست متوجه نمیشم میشه واضحتر بگین

majid325
پنج شنبه 19 فروردین 1389, 16:31 عصر
کارهایی که گفته بودید انجام دادم (به غیر از ExecuteScalar چون تا حالا باهاش کار نکردم و نمیدونستم چه مواقعی باید ازش استفاده کرد[/PHP]

روش استفاده از SQL Command (http://barnamenevis.org/forum/showthread.php?t=94296)

mehdi.mousavi
پنج شنبه 19 فروردین 1389, 16:40 عصر
کارهایی که گفته بودید انجام دادم (به غیر از ExecuteScalar چون تا حالا باهاش کار نکردم و نمیدونستم چه مواقعی باید ازش استفاده کرد)برنامه خیلی خواناتر و بهتر شد اما عجیب اینکه سرعت اجرای حلقه کمتر شد و اگه قبلا از 500 رکورد وقتی به 250 میرسید خطا میداد حالا وقتی به 150 میرسه با خطا مواجه میشم

سلام.
آخه این چه کدی هستش که نوشته اید؟ :ناراحت:

میشه مرتب و دقیق بفرمایید چیکار می خواهید کنید؟ این مدل کدی که شما نوشتید رو قاعدتا میشه با یه دستور SQL انجام داد. نه اینکه برای هر کار جزیی، یه round-trip بین Client و SQL Server داشته باشید و در نهایت سیستم رو به زانو در بیارید.

اما در مورد ContextSwitchDeadlock.... آیا این پیام رو هنگام Debug کردن برنامه می گیرید؟ با برنامه رو اگر بصورت standalone هم اجرا کنید، باز این اتفاق رخ میده؟

اگر در Visual Studio رخ میده، می تونید از منوی Debug گزینه Exceptions رو انتخاب کنید، سپس به بخش Managed Debug Assistants برید و اونجا گزینه ContextSwitchDeadlock رو خاموش کنید.

البته، پر واضحه که کد شما خیلی بد نوشته شده، اگر صورت مساله رو دقیق توضیح بدید، خدمتتون عرض میکنم چطوری بنویسیدش که بخوبی کار کنه.

موفق باشید.

majid325
پنج شنبه 19 فروردین 1389, 16:51 عصر
باید بین هر 20 تا 30 تا insert یک بار application.DoEvents رو کال کنید تا کارتون راه بیافته.یا از یه ترد دیگه استفاده کنید.

آره اینم یه تست بزن

saeidcd
شنبه 21 فروردین 1389, 12:17 عصر
باز هم از همه ممنون
اول از همه نمیتونم از ترد استفاده کنم چون میخواهم بعد از خطا هم برنامه کامل ادامه پیدا کنه

من توی برنامه نویسی خیلی مبتدی هستم و خیلی وقت نیست که شروع کردم شما اینقدر
میگین کدت بده که ادم رو ناامید میکنین

استاد عزیز mehdi.mousavi (http://barnamenevis.org/forum/member.php?u=41233) هم تو برنامه و موقع debug این مشکل بوجود میاد ContextSwitchDeadlock رو خاموش کردم مشکل حل شد مرسی

اما در مورد کد بدم که گفتین سوال رو کامل شرح میدم تا اگه دوستان لطف کنن و بگن چطور بنویسم که کد بهتر و حرفه ای تر بشه
***
من باید تمام صفحات یک سایت رو بخونم و یه اطلاعاتی رو بگیرم و تو دیتابیس ذخیره کنم
اولین کار اینه که ادرس تمام صفحات ذخیره بشه برای این کار از اولین صفحه شروع میکنم تمام لینکهای تو اون صفحه رو میخونم و تو دیتابیس ذخیره میکنم بعد برنامه اولین لینکی رو که بررسی نشد رو از دیتابیس میخونه و مثل قبلی تمام لینکهای این صفحه رو که قبلا تو دیتابیس ذخیره نشده بود رو ذخیره میکنه (تعداد لینکها توی این صفحه حدو 500 لینک برای هر صفحه هست) و به همین ترتیب تا دیگه هیچ url تو دیتابیس نباشه که بررسی نشد (تا الان حدود رکورد که همون url صفحات هست و تکراری نیست رو ذخیره کرده 723727)
بعد باید بدونم که هر صفحه به کجاها لینک داده پس ایدی هر دو تا صفحه رو تو یه تیبل دیگه ذخیره میکنم و تعداد لینک هایی که داده مثلا صفحه با ای دی 1 به صفحات 3و4و5و9 لینک داده که به صفحه 3 -2 بار لینک داده
در اخر هم لینکی رو که بررسی کردم مشخص میکنم تا بدونم که چک شده

****

حالا لطفا کمک کنید و بگید که چطور کد خوشگلتر بنوسم تا سیستم هم به زانو در نیاد از وقتی که تا حالا گذاشتین ممنون

saeidcd
سه شنبه 24 فروردین 1389, 17:55 عصر
اساتید گرامی اگه بازهم نامفهوم بود بگین تا بیشتر توضیح بدم