PDA

View Full Version : سوال: مفهوم صحیح اتصال به بانک اطلاعاتی sql server و بستن رکوردستها



mohammadsaleh
دوشنبه 01 اردیبهشت 1399, 19:59 عصر
سلام
چند وقتی است با استفاده از اطلاعات این تالار و اینترنت تلاش می کنم بتوانم با استفاده از دیتابیس های قدرتمند sql server کار کنم. بدیهی است برای این ارتباط از adodb بهره گرفته میشود
بافرض فراهم شدن همه مقدمات حالا قرار است از طریق دستورات با جداول دیتابیس ارتباط برقرار کرده و به خوانش، ویرایش، حذف و افزودن بپردازیم
آنچه در همه جا گفته میشود این است که برای کار روی یک جدول اقدامات زیر انجام شود
کنکشن
بازکردن رکوردست
انجام عملیات
بستن رکوردست
بستن کنکشن

سئوالات اساسی که برای من پیش آمده این است که
1- آیا این باز و بستن کنکشن یکبار کفایت می کند یا خیر. منظورم این است که در اولین فرم برنامه اتصال به دیتابیس برقرار و در موقع خروج از برنامه این اتصال بسته شود
2- در خصوص رکوردستها چطور؟ آیا لازم است برای هر عملیات این کار انجام شود. و آیا این بازو بستن متوالی جداول در برنامه های چندکاربره ضروری است.
3- در خصوص recordcount برخلاف dao که شمارش دقیقی از اطلاعات درخواستی می دهد در ado کمی پیچیده بوده وحداقل برای من حل نشده باقی مانده است. و دستورات موجود به خوبی عمل نمی کنند.

mazoolagh
سه شنبه 02 اردیبهشت 1399, 11:36 صبح
1- میتونین یک کانکشن گلوبال برای کل برنامه تعریف کنین، بهتر هم هست.
باید یک روال پابلیک برای بازکردن این کانکشن بنویسین که فقط در صورت لزوم اون رو باز کنه - قبل از باز کردن هر رکوردست از این تابع استفاده میکنین.

یک چیزی شبیه زیر:
public const cons as string="..."
public conn as adodb.connection

public sub open_conn()
on error goto error_handler
if conn is nothing then
set conn=new adodb.connection
end if
if conn.connectionstring="" then
conn.connectionstring=cons
end if
if conn.state=adstateclosed then
conn.open
end if
exit sub
error_handler:
msgbox "error : " & err.number & vbcrlf & err.description , vbcritical
end sub

mazoolagh
سه شنبه 02 اردیبهشت 1399, 11:57 صبح
2- این پرسش خیلی کلی هست!
رکوردست های readonly رو که معمولا در کمبو ها و لیست ها استفاده میشه میتونین گلوبال تعریف کنین
اگر منظور این هست که کل یک جدول رو در یک رکوردست updateable گلوبال بریزین، فکر نکنم کار خوبی باشه؛
در هر فرم یا روتین، بسته به نیاز فقط رکوردهای لازم رو بریزین تو رکوردست و کارتون که تموم شد رکوردست رو ببندین.

برای بازکردن رکوردست هم دو تابع پابلیک بنویسین، یکی برای readonly و یکی هم برای updateable
که sql select رو بعنوان پارامتر بگیره و adodb.recordset برگردونه.
از connection پابلیک پست قبلی یعنوان کانکشن رکوردست استفاده کنین.

mazoolagh
سه شنبه 02 اردیبهشت 1399, 11:58 صبح
public function getrs(sql as string) as adodb.recordset
on error goto error_handler
set getrs=new adodb.recordset
open_conn
if conn.state=adstateopen then
with getrs
.activeconnection=conn
.source=sql
.locktype=adlockoptimistic
.cursortype=adopendynamic
.cursorlocation=aduseclient
.open
end with
else
msgbox "conn closed"
end if
exit function
error_handler:
msgbox "error : " & err.number & vbcrlf & err.description, vbcritical
end function

mazoolagh
سه شنبه 02 اردیبهشت 1399, 12:05 عصر
public function getrs_readonly(sql as string) as adodb.recordset
on error goto error_handler
set getrs_readonly=new adodb.recordset
open_conn
if conn.state=adstateopen then
with getrs_readonly
.activeconnection=conn
.source=sql
.cursortype=adopenforwardonly
.locktype=adlockreadonly
.cursorlocation=aduseclient
.open
.activeconnection=nothing
end with
else
msgbox "conn closed"
end if
exit function
error_handler:
msgbox "error : " & err.number & vbcrlf & err.description, vbcritical
end function

mazoolagh
سه شنبه 02 اردیبهشت 1399, 12:07 عصر
3- از چه cursortype , cursorlocation استفاده کردین؟

mohammadsaleh
سه شنبه 02 اردیبهشت 1399, 18:38 عصر
3- از چه cursortype , cursorlocation استفاده کردین؟

سلام
باتشکر از پاسختون. بله همین کار را کرده ام. منتهی منظورم این است که بعد از بازکردن رکوردست و انجام عملیات و بستن رکوردست لازم است کنکشن هم بسته شود یا خیر. یعنی هر کاربر یکبار به دیتابیس وصل شود و موقع بستن برنامه هم کلوز شود
البته چون هدف واکشی اطلاعات است قطعا بخشی از رکوردهای جدول- یک یا چند رکورد- با دستورات SELECT انتخاب می شوند

در مورد سئوالی که فرمودید به شکل زیر استفاده می کنم


With Rst4
'.ActiveConnection = cn
.CursorLocation = adUseClient
.CursorType = adOpenKeyset
.LockType = adLockOptimistic
' .Source = Sql
.Open SQL4, cn, adCmdText
End With

بدیهی است دیتابیس شامل جداول گوناگون است و ممکن است در یک عملیات چندین جدول برای استخراج اطلاعات خاص برای نمایش لازم به گشودن باشند و نهایتا برروی چند جدول هم همزمان اطلاعات خاصی ویرایش و یا افزوده شود

eb_1345
چهارشنبه 03 اردیبهشت 1399, 01:34 صبح
End With[/CODE]
بدیهی است دیتابیس شامل جداول گوناگون است و ممکن است در یک عملیات چندین جدول برای استخراج اطلاعات خاص برای نمایش لازم به گشودن باشند و نهایتا برروی چند جدول هم همزمان اطلاعات خاصی ویرایش و یا افزوده شود
سلام
با اجازه جناب mazoolagh (https://barnamenevis.org/member.php?9893-mazoolagh)
فقط در زمان خروج از برنامه دستور بستن کانکشن را واردکن!
موفق باشی

mazoolagh
پنج شنبه 04 اردیبهشت 1399, 09:49 صبح
همین که دوستمون فرمودن درست هست.
شما حتی نیازی نیست که در ابتدای برنامه کانکش رو باز کنین (اگر از کدی که گذاشتم استفاده کردین)،
موقع بستن برنامه اگر کانکشن رو ببندین مطمئنتر هست ولی نبستین هم مشکل خاصی نیست.

مشکل وقتی هست که ابجکت های مختلف بسازین و اون ها رو رها کنین.

mazoolagh
پنج شنبه 04 اردیبهشت 1399, 09:51 صبح
مشکل با recordcount رو توضیح ندادین که سرنوشتش چی شد؟

mohammadsaleh
پنج شنبه 04 اردیبهشت 1399, 22:58 عصر
با استفاده از کد آزمایشی زیر تونستم شماش درست رو انجام بدم

Private Sub cmdRecordCount_Click()
On Error GoTo Catch


Dim strSql As String
Dim objRst1 As ADODB.Recordset
Dim objRst2 As ADODB.Recordset
Dim objRst3 As ADODB.Recordset
Dim objRst4 As ADODB.Recordset




Call ConnectToServer1
'' Get all categories from local Northwind database.
strSql = "SELECT * FROM dbo.tblSepordeh WHERE NumHesab=47100 "

'' In code below, because we didn't specify cursor location, it's server-side by default.

'' Returns -1
Set objRst1 = New ADODB.Recordset
objRst1.Open strSql, cn, adOpenForwardOnly


'' Returns -1
Set objRst2 = New ADODB.Recordset
objRst2.Open strSql, cn, adOpenDynamic


'' Returns valid count
Set objRst3 = New ADODB.Recordset
objRst3.Open strSql, cn, adOpenKeyset


'' Returns valid count
Set objRst4 = New ADODB.Recordset
objRst4.Open strSql, cn, adOpenStatic

'' Display the number of records in Immediate window.
MsgBox "objRst1 (adOpenForwardOnly) record count: " & objRst1.RecordCount
MsgBox "objRst2 (adOpenDynamic) record count: " & objRst2.RecordCount
MsgBox "objRst3 (adOpenKeyset) record count: " & objRst3.RecordCount
MsgBox "objRst4 (adOpenStatic) record count: " & objRst4.RecordCount


'' Clean up
objRst1.Close
objRst2.Close
objRst3.Close
objRst4.Close
Set objRst1 = Nothing
Set objRst2 = Nothing
Set objRst3 = Nothing
Set objRst4 = Nothing

Exit Sub

Catch:
MsgBox "cmdRecordCount_Click()" & vbCrLf & vbCrLf _
& "Error#: " & err.number & vbCrLf & vbCrLf & err.Description
End Sub




البته ظاهرا باید از adOpenKeyset یا adOpenStatic استفاده کنم تا شمارش دقیقی از خواسته من نشان بدهد
راستی این کد ها به نست کد شما خلاصه و در یک خط آمده و برخی خصوصیات حذف شده است.
ممنون میشم در این مورد هم راهنمایی بفرمایید مثل گذشته که راهنمایی خوبی بوده اید استاد.

mazoolagh
سه شنبه 09 اردیبهشت 1399, 13:26 عصر
البته ظاهرا باید از adOpenKeyset یا adOpenStatic استفاده کنم تا شمارش دقیقی از خواسته من نشان بدهد


در اصل cursorlocation عامل مهمتری هست:
اگر سمت client استفاده کنین مشکلی با recordcount نباید داشته باشین،
ولی اگر سمت server باشه اونوقت باید cursortype یکی از دو حالتی باشه که نوشتین.

بطور کلی بهتره cursorlocation رو سمت client بگذارین.
در ضمن به یاد داشته باشین که اگر پارامتری مقدارش با بقیه پارامترها ناسازگار باشه پیغام خطایی نمیگیرین، خود provider مقدار دیگه ای جایگزین میکنه.



راستی این کد ها به نست کد شما خلاصه و در یک خط آمده و برخی خصوصیات حذف شده است.

1- خوانایی بهتر بخصوص برای اینجا که یادگیری هم مهمه
2- وقتی از with استفاده میکنین دیگه لازم نیست یک object تعریف و بعد حذفش کنین
3- اون خصوصیات بعضیاش بهتره مقداردهی بشن بخصوص cursorlocation که پیشفرض serverside هست و اثرش رو توضیح دادم