Theory
वह रात जब Bills Survive करते हैं
आज रात graduation है: cashier Save click करता है, ShopKeeper bill को ShopDB में लिखता है, power जितना चाहे flicker कर सकता है, और कल day report सब कुछ वापस पढ़ती है।
हर हिस्सा आपके पास पहले से है: tested connection string, 5-object model, BCA205 का SQL, Unit 3 का Try/Catch, और अपना DataSource wait कर रहा एक DataGrid। यह lesson सिर्फ़ ASSEMBLE करता है: तीन code shapes (connected read, write, disconnected fill) जो साथ मिलकर हर ADO.NET exam program cover करती हैं जो यह paper सेट करता है।
Practical
Shape 1 और 2: Connected Read, फिर एक Write
Imports System.Data.SqlClient
Module BillStore
Dim cs As String = "Data Source=.;Initial Catalog=ShopDB;Integrated Security=True"
Sub ReprintBill(ByVal billNo As Integer)
Dim cn As New SqlConnection(cs)
Try
cn.Open() ' dial
Dim cmd As New SqlCommand( _
"SELECT Item, Amount FROM Bills WHERE BillNo = " & billNo, cn)
Dim rd As SqlDataReader = cmd.ExecuteReader()
While rd.Read() ' one row per pass
MsgBox(rd("Item") & " Rs " & rd("Amount"))
End While
rd.Close()
Catch ex As Exception
MsgBox("Database error: " & ex.Message)
Finally
cn.Close() ' always hang up
End Try
End Sub
Sub SaveLine(ByVal item As String, ByVal amount As Decimal)
Dim cn As New SqlConnection(cs)
cn.Open()
Dim ins As New SqlCommand( _
"INSERT INTO Bills(Item, Amount) VALUES('" & item & "', " & amount & ")", cn)
Dim rows As Integer = ins.ExecuteNonQuery() ' 1 row affected
cn.Close()
End Sub
End Module
Theory
Read को पढ़ना
ReprintBill के बीच वाले हिस्से से चलिए:
- ExecuteReader() SELECT भेजता है और एक live SqlDataReader return करता है
- rd.Read() अगली row पर advance करता है, rows बचे रहने तक True answer देता है: natural While loop; हर column नाम से पहुँचा जा सकता है,
rd("Item") - forward-only का मतलब है कोई दूसरा pass नहीं: rows को फिर से walk करने के लिए, re-execute कीजिए
और नोटिस कीजिए Close() कहाँ बैठता है: connection Finally में बंद होता है, तो एक mid-read exception भी line hang up करता है। Unit 3 की grammar, Unit 5 के resource की guarding कर रही है: यह pairing वह है जिसे examiners good practice कहते हैं और accordingly mark करते हैं।
Practical
Shape 3: Disconnected Fill
Sub LoadDayReport()
Dim cn As New SqlConnection(cs)
Dim da As New SqlDataAdapter("SELECT * FROM Bills", cn)
Dim ds As New DataSet()
da.Fill(ds, "Bills") ' opens AND closes cn by itself
dgvBill.DataSource = ds.Tables("Bills") ' Unit 3's glass, filled
' owner edits rows in the grid... later:
' da.Update(ds, "Bills") ' pushes changes back to ShopDB
End Sub
Sub ShowDayTotal()
Dim cn As New SqlConnection(cs)
cn.Open()
Dim cmd As New SqlCommand("SELECT SUM(Amount) FROM Bills", cn)
Dim total As Decimal = CDec(cmd.ExecuteScalar()) ' one single value
cn.Close()
MsgBox("Today: Rs " & total)
End Sub
Quiz
Dim rows As Integer = ins.ExecuteNonQuery() एक single-row INSERT successfully run करता है। rows में क्या है, और ExecuteNonQuery किसके लिए built है?
- 1: यह affected rows की संख्या return करता है, और यह INSERT/UPDATE/DELETE के लिए exist करता है
- 0: यह एक success flag return करता है जहाँ 0 का मतलब है कोई error नहीं
- नई row का data: यह वो return करता है जो statement ने produce किया
- यह एक INSERT run नहीं कर सकता: ADO.NET में सिर्फ़ SELECT statements execute होते हैं
Show the answer
1: यह affected rows की संख्या return करता है, और यह INSERT/UPDATE/DELETE के लिए exist करता है
ExecuteNonQuery उस SQL के लिए verb है जो rows return करने के बजाय data CHANGE करता है, और इसका Integer answer touched rows गिनता है: इस insert के लिए 1, एक broad UPDATE के लिए शायद दर्जनों, 0 का मतलब है कुछ match नहीं हुआ (जिसे option B success समझने की ग़लती करता है: एक 0 अक्सर signal करता है आपके WHERE clause को कोई नहीं मिला)। Rows-returning काम ExecuteReader का है, single values ExecuteScalar के: 3 executes को उनके SQL kinds से match करना इस unit का सबसे reliable exam question है। Real code में यह count check करना silent failures पकड़ता है।
Think first
Fill के लिए Connection किसने Open किया?
LoadDayReport कभी cn.Open() या cn.Close() call नहीं करता, फिर भी यह काम करता है और कुछ leak नहीं करता। ReprintBill को दोनों करने पड़े। Tap करने से पहले फ़र्क explain कीजिए।
Show the answer
DataAdapter.Fill connection खुद manage करता है: इसे बंद पाकर, यह खोलता है, rows को DataSet में खींचता है, और फिर से बंद कर देता है: एक self-contained trip, जो exactly disconnected philosophy है। READER यह नहीं कर सकता: यह एक live line पर stream करता है, तो जितनी देर आप Read() करें line खुली रहनी ज़रूरी है, और बंद करना आपकी responsibility बन जाता है (इसलिए Finally)। Exam sentence: Fill connection को automatically open और close करता है; एक DataReader को इसकी पूरी lifetime के लिए एक explicitly open connection चाहिए।
Watch out
Habits जो Pass को Distinction से अलग करती हैं
Unclosed Connections: हर एक database slot hold करता है; एक busy till तब तक leak करता रहता है जब तक server refuse न कर दे। हर path पर Finally में Close कीजिए।
User Text को SQL में Glue करना: हमारी teaching listings readability के लिए concatenate करती हैं, पर O'Brien नाम का एक item string तोड़ देता है, और worse भी possible है: professional fix की तरह parameterised commands (cmd.Parameters) mention कीजिए और examiners nod करते हैं।
ग़लत Execute: एक INSERT पर ExecuteReader, एक SELECT पर ExecuteNonQuery: दोनों run होते हैं, दोनों useless results देते हैं। Verb को SQL से match कीजिए।
Theory
ShopKeeper, Complete
पीछे मुड़कर देखिए: एक Windows Forms face (Unit 3), Items, Bills और GST-polymorphic Products का एक OOP heart (Unit 4), और अब वह memory जो रात survive करती है (Unit 5), सब उस CLR machinery पर चलते हुए जिसे आप शुरू से आख़िर तक narrate कर सकते हैं (Units 1 और 2)। यही पूरा BCA404 syllabus है जो एक till में जी रहा है। जब BCA503-01 आपको बाद में server-side data access देगी, यह exact object model नए names के साथ लौटेगा, और आप इसे एक पुराने supplier की तरह greet करेंगे।
Summary
Key takeaways
- Connected read: Open, Command + ExecuteReader, rd("Column") वाला While rd.Read(), Finally में Close।
- Writes: INSERT/UPDATE/DELETE के लिए ExecuteNonQuery, affected-row count return करते हुए (एक single insert के लिए 1; 0 अक्सर मतलब है WHERE कुछ match नहीं हुआ)।
- Single values: ExecuteScalar (SUM, COUNT): एक call, एक result।
- Disconnected: DataAdapter.Fill(ds, "Bills") आपके लिए open AND close करता है; ds.Tables("Bills") bind कीजिए; Update(ds) edits sync करता है।
- Database काम को Try/Catch/Finally में wrap कीजिए; error path पर connection कभी open मत छोड़िए।
- Real code में concatenated SQL के बजाय parameterised commands prefer कीजिए।
- Memory hook: readers line hold करते हैं, adapters trip करते हैं, counts बताते हैं क्या हुआ।