Đánh giá chủ đề:
  • 0 Votes - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[Help] Tại sao Ado recordset inner join readonly
#1
Có bạn nào giúp với :

1, Code kết nối như sau

Mã:
Option Compare Database
Public conn As ADODB.Connection
Function get_constrN() As String
   Dim myPath As String
   Dim myPass As String
   myPath = CurrentProject.Path & "\" & "van_de_ado_be.accdb"
   myPass = ""
   get_constrN = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & myPath & ";Jet OLEDB:Database Password=" & myPass & ";"
End Function
Function getRs(sql As String) As ADODB.Recordset
   'Dim conn As ADODB.Connection
   Dim rs As ADODB.Recordset
   
   Set conn = New ADODB.Connection
   If conn.State = adStateClosed Then
       conn.ConnectionString = get_constrN
       conn.Open
   Else
   End If
   
   Set rs = New ADODB.Recordset
   rs.CursorLocation = adUseClient
   rs.CursorType = adOpenStatic
   rs.LockType = adLockOptimistic
   rs.Open sql, conn
   Set getRs = rs
End Function

2, thực hiện với table thì ok, thêm xóa sửa được

Mã:
Private Sub Form_Open(Cancel As Integer)
   Set Me.Recordset = MyAdo.getRs("select * from phieu")
End Sub

3, Thực hiện với Que ry có inner join thì tắt tịt , readonly ? làm sao đây?

Mã:
Private Sub Form_Open(Cancel As Integer)
   Dim sql As String
sql = " SELECT phieu.phieu_id, phieu.khach_id, phieu.loai, khach.ten, khach.tel"
sql = sql & " FROM khach INNER JOIN phieu ON khach.khach_id = phieu.khach_id"
   Set Me.Recordset = MyAdo.getRs(sql)
End Sub
Chữ ký của thucgia Hix, Access quả nhiên lợi hại !!!! http://vibigaba.esy.es/
ღღღღღTài sản của thucgia (View All Items) ღღღღღ
Reply
Những người đã cảm ơn
#2
Bạn thử đổi câu lệnh sql xem thử.
Mã PHP:
sql " SELECT T2.phieu_id, T2.khach_id, T2.loai, T1.ten, T1.tel"

sql sql " FROM khach T1, phieu T2 WHERE T1.khach_id = T2.khach_id" 
Chữ ký của ongke0711 If you BORN poor, it's not your mistake. But if you DIE poor, It's your mistake!
ღღღღღTài sản của ongke0711 (View All Items) ღღღღღ
Reply
Những người đã cảm ơn Noname
#3
(18-10-15, 02:00 PM)ongke0711 Đã viết: Bạn thử đổi câu lệnh sql xem thử.
Mã PHP:
sql " SELECT T2.phieu_id, T2.khach_id, T2.loai, T1.ten, T1.tel"

sql sql " FROM khach T1, phieu T2 WHERE T1.khach_id = T2.khach_id" 

không được bạn à vẫn read only!!!

search mấy ngày rồi mình thấy là vô phương, nhưng mình nghĩ nó khoá là có lý của nó
Nên mình tìm thấy một hướng mới đó là cho nó updateable bằng cách ngắt kết nối

Mã:
Private Sub Form_Open(Cancel As Integer)
   Dim sql As String
   Dim rs As ADODB.Recordset
sql = " SELECT phieu.phieu_id, phieu.khach_id, phieu.loai, khach.ten, khach.tel"
sql = sql & " FROM khach INNER JOIN phieu ON khach.khach_id = phieu.khach_id"
   Set rs = MyAdo.getRs(sql)
   rs.ActiveConnection = Nothing
   Set Me.Recordset = rs
End Sub

nhưng lúc này ta phải tự cập nhật sự thay đổi bằng cách dùng hàm Di rty

Đang nghiên cứu, có cách nào thì cùng trao đổi nhé.
Chữ ký của thucgia Hix, Access quả nhiên lợi hại !!!! http://vibigaba.esy.es/
ღღღღღTài sản của thucgia (View All Items) ღღღღღ
Reply
Những người đã cảm ơn
#4
(18-10-15, 02:18 PM)thucgia Đã viết:
(18-10-15, 02:00 PM)ongke0711 Đã viết: Bạn thử đổi câu lệnh sql xem thử.
Mã PHP:
sql " SELECT T2.phieu_id, T2.khach_id, T2.loai, T1.ten, T1.tel"

sql sql " FROM khach T1, phieu T2 WHERE T1.khach_id = T2.khach_id" 

không được bạn à vẫn read only!!!

search mấy ngày rồi mình thấy là vô phương, nhưng mình nghĩ nó khoá là có lý của nó
Nên mình tìm thấy một hướng mới đó là cho nó updateable bằng cách ngắt kết nối

Mã:
Private Sub Form_Open(Cancel As Integer)
   Dim sql As String
   Dim rs As ADODB.Recordset
sql = " SELECT phieu.phieu_id, phieu.khach_id, phieu.loai, khach.ten, khach.tel"
sql = sql & " FROM khach INNER JOIN phieu ON khach.khach_id = phieu.khach_id"
   Set rs = MyAdo.getRs(sql)
   rs.ActiveConnection = Nothing
   Set Me.Recordset = rs
End Sub

nhưng lúc này ta phải tự cập nhật sự thay đổi bằng cách dùng hàm Di rty

Đang nghiên cứu, có cách nào thì cùng trao đổi nhé.

Có lẽ làm được rồi

1, ở sự kiện open frm -> ngắt kết nối cho phép rs có thể updateable

Mã:
Private Sub Form_Open(Cancel As Integer)
   Dim sql As String
   Dim rs As ADODB.Recordset
sql = " SELECT phieu.phieu_id, phieu.khach_id, phieu.loai, khach.ten, khach.tel"
sql = sql & " FROM khach INNER JOIN phieu ON khach.khach_id = phieu.khach_id"
   Set rs = MyAdo.getRs(sql)
   rs.ActiveConnection = Nothing
   Set Me.Recordset = rs
End Sub

2,Ở sự kiện before update nếu là me.Dirty = true


Mã:
Private Sub Form_BeforeUpdate(Cancel As Integer)
   If Me.Dirty Then
       'MsgBox "ban phai luu su thay doi"
       'MsgBox Me.phieu_id & Me.khach_id & Me.loai
       'hien thi thong bao co muon thay doi if yes
       Dim p As dto_phieu
       Set p = New dto_phieu
       p.phieu_id = Me.phieu_id
       p.khach_id = Me.khach_id
       p.loai = Me.loai
       Call ado2_phieu.Sua(p)                 'tien hanh sua phieu
       Dim k As dto_khach
       Set k = ado2_khach.TimKiem(p.khach_id)
       Me.ten = k.ten
       Me.tel = k.tel                         'hien thi lai khach tuong ung
       Set k = Nothing                        'giai phong obj
       Set p = Nothing
       'if no thì        Cancel = True
   End If
End Sub


3, Làm như thế thì access chẳng thua kém gì tụi víial studio cả


4, Chuyển đổi giao diện từ access truyền thống sang Ado thì khá phức tạp nhưng tận dụng được tính năng visible và một số tính năng wizard!!!!

Có gì thì cùng thảo luận nhé các bạn.
Chữ ký của thucgia Hix, Access quả nhiên lợi hại !!!! http://vibigaba.esy.es/
ღღღღღTài sản của thucgia (View All Items) ღღღღღ
Reply
Những người đã cảm ơn Noname , ongke0711 , maidinhdan
#5
Chào bạn !
ADO chạy với table hay Query đều ổn cả. Nhưng hơi chậm hơn chạy DAO và chạy trực tiếp.
Hiện mình đã chuyển toàn bộ PM bán hàng của mình sang ADO. Đã gần xong rồi.
Rất mong được trao đổi và chia sẽ cũng các Pro.
Thân./.
Reply
Những người đã cảm ơn Noname
#6
(23-10-15, 09:46 PM)Minh Tiên Đã viết: Chào bạn !
ADO chạy với table hay Query đều ổn cả. Nhưng hơi chậm hơn chạy DAO và chạy trực tiếp.
Hiện mình đã chuyển toàn bộ PM bán hàng của mình sang ADO. Đã gần xong rồi.
Rất mong được trao đổi và chia sẽ cũng các Pro.
Thân./.

Bạn biết cái UpdateBatch không? chỉ mình với!!!

Mình tìm thấy đoạn này

Mã:
Set rstName = New ADODB.Recordset
With rstName
  .ActiveConnection = cnnName
  .CursorType = adKeyset
.CursorLocation = adUseClient
.LockEdits = adBatchOptimistic
.Open ";SELECT * FROM TableName WHERE Criteria", Options:=adCmdText
Set .ActiveConnection = Nothing 'Disconnect the Recordset
'Close the connection to the server, if desired
'Edit the field values of multiple records here
'You also can append and delete records
'Reopen the server connection, if closed
Set .ActiveConnection = cnnName
.UpdateBatch 'Send all changes to the data source
End With
rstName.Close

nhưng nó chỉ update 1 dòng!!!!
chứ không cập nhật toàn bộ recordset (bao gồm thêm, xóa,sửa)

cái kiểu này nó gọi là ngắt kết nối hoàn toàn trong lúc user thêm xóa ....
Đến khi muốn lưu thì bấm nút một cái , dữ liệu sẽ cập nhật vào csdl, rồi lại đóng kết nối

Bạn có làm theo cái hướng này không, nếu có cho mình xin cái bản demo
Chữ ký của thucgia Hix, Access quả nhiên lợi hại !!!! http://vibigaba.esy.es/
ღღღღღTài sản của thucgia (View All Items) ღღღღღ
Reply
Những người đã cảm ơn
#7
(24-10-15, 12:15 AM)thucgia Đã viết: Bạn biết cái UpdateBatch không? chỉ mình với!!!

Mình tìm thấy đoạn này

Mã:
Set rstName = New ADODB.Recordset
With rstName
  .ActiveConnection = cnnName
  .CursorType = adKeyset
.CursorLocation = adUseClient
.LockEdits = adBatchOptimistic
.Open ";SELECT * FROM TableName WHERE Criteria", Options:=adCmdText
Set .ActiveConnection = Nothing 'Disconnect the Recordset
'Close the connection to the server, if desired
'Edit the field values of multiple records here
'You also can append and delete records
'Reopen the server connection, if closed
Set .ActiveConnection = cnnName
.UpdateBatch 'Send all changes to the data source
End With
rstName.Close

nhưng nó chỉ update 1 dòng!!!!
chứ không cập nhật toàn bộ recordset (bao gồm thêm, xóa,sửa)

cái kiểu này nó gọi là ngắt kết nối hoàn toàn trong lúc user thêm xóa ....
Đến khi muốn lưu thì bấm nút một cái , dữ liệu sẽ cập nhật vào csdl, rồi lại đóng kết nối

Bạn có làm theo cái hướng này không, nếu có cho mình xin cái bản demo

Theo mình biết thì Access không hỗ trợ UpdateBatch đối với form Recordset

MTNQ cũng đang viết  một ứng dụng Access sử dụng ADO nhưng bận quá nên bỏ dở khá lâu rùi. Thấy các bác "châm ngòi " nên lại lao vào  014

Cái UpdateBatch này cũng hay nhưng lột sạch quần áo của bác Google cũng chẵng thấy lòi ra được phương án nào khả thi cho BoundForm   015  (MTNQ thường dùng cho Subform Datasheet hoặc Continuous )

Mất cả buổi tối cuối cùng cũng tìm ra được một phương án có vẻ khả quan: đó là sử dụng một Recordset trung gian
-Khi mở form thiết lập kết nối, lấy về  bản ghi làm nguồn cho form đồng thời tạo thêm một bản sao  (Tạm gọi là rst1)
-Ngắt kết nối đến CSDL
-Mỗi khi thêm, xóa, sửa ta đều update vào rst1, khi người dùng nhấn nút Lưu thì thiết lập kết nối cho rst1 và gọi  UpdateBatch 

Đây là bản Demo mình mới làm, bạn xem thử và cùng thảo luận nhé 

Demo UpdateBatch.rar
Chữ ký của MatTroiNguQuen Thời gian nước chảy... da mòn
Ngủ quên một chốc thấy còn bộ xương!
Reply
Những người đã cảm ơn thucgia , Noname , maidinhdan
#8
(25-10-15, 03:59 AM)MatTroiNguQuen Đã viết:
(24-10-15, 12:15 AM)thucgia Đã viết: Bạn biết cái UpdateBatch không? chỉ mình với!!!

Mình tìm thấy đoạn này

Mã:
Set rstName = New ADODB.Recordset
With rstName
  .ActiveConnection = cnnName
  .CursorType = adKeyset
.CursorLocation = adUseClient
.LockEdits = adBatchOptimistic
.Open ";SELECT * FROM TableName WHERE Criteria", Options:=adCmdText
Set .ActiveConnection = Nothing 'Disconnect the Recordset
'Close the connection to the server, if desired
'Edit the field values of multiple records here
'You also can append and delete records
'Reopen the server connection, if closed
Set .ActiveConnection = cnnName
.UpdateBatch 'Send all changes to the data source
End With
rstName.Close

nhưng nó chỉ update 1 dòng!!!!
chứ không cập nhật toàn bộ recordset (bao gồm thêm, xóa,sửa)

cái kiểu này nó gọi là ngắt kết nối hoàn toàn trong lúc user thêm xóa ....
Đến khi muốn lưu thì bấm nút một cái , dữ liệu sẽ cập nhật vào csdl, rồi lại đóng kết nối

Bạn có làm theo cái hướng này không, nếu có cho mình xin cái bản demo

Theo mình biết thì Access không hỗ trợ UpdateBatch đối với form Recordset

MTNQ cũng đang viết  một ứng dụng Access sử dụng ADO nhưng bận quá nên bỏ dở khá lâu rùi. Thấy các bác "châm ngòi " nên lại lao vào  014

Cái UpdateBatch này cũng hay nhưng lột sạch quần áo của bác Google cũng chẵng thấy lòi ra được phương án nào khả thi cho BoundForm   015  (MTNQ thường dùng cho Subform Datasheet hoặc Continuous )

Mất cả buổi tối cuối cùng cũng tìm ra được một phương án có vẻ khả quan: đó là sử dụng một Recordset trung gian
-Khi mở form thiết lập kết nối, lấy về  bản ghi làm nguồn cho form đồng thời tạo thêm một bản sao  (Tạm gọi là rst1)
-Ngắt kết nối đến CSDL
-Mỗi khi thêm, xóa, sửa ta đều update vào rst1, khi người dùng nhấn nút Lưu thì thiết lập kết nối cho rst1 và gọi  UpdateBatch 

Đây là bản Demo mình mới làm, bạn xem thử và cùng thảo luận nhé 

Demo UpdateBatch.rar

thank for share, ý tưởng tuyệt vời, 1 rs dùng hiển thị, 1 rs dùng lưu trữ, ...à nếu không xài cái rst1 này thì chuyện gì xảy ra nhỉ?

phát hiện 1 vấn đề : khi bấm del -> chọn no nó vẫn xử luôn 014
Chữ ký của thucgia Hix, Access quả nhiên lợi hại !!!! http://vibigaba.esy.es/
ღღღღღTài sản của thucgia (View All Items) ღღღღღ
Reply
Những người đã cảm ơn Noname
#9
(25-10-15, 12:13 PM)thucgia Đã viết: thank for share, ý tưởng tuyệt vời, 1 rs dùng hiển thị, 1 rs dùng lưu trữ, ...à nếu không xài cái rst1 này thì chuyện gì xảy ra nhỉ?

phát hiện 1 vấn đề : khi bấm del -> chọn no nó vẫn xử luôn 014

-"không xài cái rst1" thì...  không xài cái UpdateBatch  014
-"khi bấm del -> chọn no nó vẫn xử luôn":
Cái vụ này thì đơn giản:

Code:
Mã:
Private Sub Form_Delete(Cancel As Integer)
    DoCmd.SetWarnings False
    If MsgBox("Ban co dong y xoa ma khach hang: " & Me.Makhachhang, vbYesNo, "luu y") = vbYes Then
        Up_To_rstData "xoa"
    Else
        Cancel = True
        DoCmd.SetWarnings True
    End If
    
End Sub

Private Sub Form_AfterDelConfirm(Status As Integer)
    DoCmd.SetWarnings True
End Sub

-Thực ra Demo trên chỉ viết để test cái vụ UpdateBatch thui. Nếu áp dụng vào thực tế thì không đơn giản vậy, cần phải kiểm soát chặt chẽ hơn khi xóa, sửa, đặc biệt là thêm mới . Trong môi trường nhiều người dùng càng phải cân nhắc về xung đột dữ liệu, cả vấn đề về tốc độ và tài nguyên khi cùng lúc mở ra 2 Recordset (Requery cũng phải làm cà 2 thằng  014 )...

-> Up lại cái Demo, thêm vào code trên, Requery sau khi lưu, thêm luôn cái nút hủy cho dễ test (lần này không dại load hết dữ liệu lên form nữa mà chỉ đưa lên top 10 thui test cho nhanh)

Demo UpdateBatch(2).rar
Chữ ký của MatTroiNguQuen Thời gian nước chảy... da mòn
Ngủ quên một chốc thấy còn bộ xương!
Reply
Những người đã cảm ơn thucgia , maidinhdan
#10
(27-10-15, 02:17 AM)MatTroiNguQuen Đã viết:
(25-10-15, 12:13 PM)thucgia Đã viết: thank for share, ý tưởng tuyệt vời, 1 rs dùng hiển thị, 1 rs dùng lưu trữ, ...à nếu không xài cái rst1 này thì chuyện gì xảy ra nhỉ?

phát hiện 1 vấn đề : khi bấm del -> chọn no nó vẫn xử luôn 014

-"không xài cái rst1" thì...  không xài cái UpdateBatch  014
-"khi bấm del -> chọn no nó vẫn xử luôn":
Cái vụ này thì đơn giản:

Code:
Mã:
Private Sub Form_Delete(Cancel As Integer)
   DoCmd.SetWarnings False
   If MsgBox("Ban co dong y xoa ma khach hang: " & Me.Makhachhang, vbYesNo, "luu y") = vbYes Then
       Up_To_rstData "xoa"
   Else
       Cancel = True
   End If
   DoCmd.SetWarnings True
End Sub

-Thực ra Demo trên chỉ viết để test cái vụ UpdateBatch thui. Nếu áp dụng vào thực tế thì không đơn giản vậy, cần phải kiểm soát chặt chẽ hơn khi xóa, sửa, đặc biệt là thêm mới . Trong môi trường nhiều người dùng càng phải cân nhắc về xung đột dữ liệu, cả vấn đề về tốc độ và tài nguyên khi cùng lúc mở ra 2 Recordset (Requery cũng phải làm cà 2 thằng  014 )...

-> Up lại cái Demo, thêm vào code trên, Requery sau khi lưu, thêm luôn cái nút hủy cho dễ test (lần này không dại load hết dữ liệu lên form nữa mà chỉ đưa lên top 10 thui test cho nhanh)

Demo UpdateBatch(2).rar

vô vàn cảm kích...quá chuẩn luôn.

-1,Nhưng còn vấn đề table có primary key hoặc autonumber thì chắc là phức tạp hở bạn.

-2,Nếu ADO ngon rồi thì tại sao Microsoft ra cái thằng ADO.net để làm gì!!!!
-3, Bạn có nghiên cứu cái này chưa?

Mã:
Dim rstADO As ADODB.Recordset
Dim fld As ADODB.Field

Set rstADO = New ADODB.Recordset
With rstADO
   .Fields.Append "EmployeeID", adInteger, , adFldKeyColumn
   .Fields.Append "FirstName", adVarChar, 10, adFldMayBeNull
   .Fields.Append "LastName", adVarChar, 20, adFldMayBeNull
   .Fields.Append "Email", adVarChar, 64, adFldMayBeNull
   .Fields.Append "Include", adInteger, , adFldMayBeNull
   .Fields.Append "Selected", adBoolean, , adFldMayBeNull

   .CursorType = adOpenKeyset
   .CursorLocation = adUseClient
   .LockType = adLockPessimistic
   .Open
End With
link : http://www.databasejournal.com/features/...rdsets.htm

Mình thắc mắc là tại sao nó không cho add dữ liệu ? thk.

- ps định phân trang giống web luôn hả?
Chữ ký của thucgia Hix, Access quả nhiên lợi hại !!!! http://vibigaba.esy.es/
ღღღღღTài sản của thucgia (View All Items) ღღღღღ
Reply
Những người đã cảm ơn


Có thể liên quan đến chủ đề
Chủ đề: Tác giả Trả lời: Xem: Bài mới nhất
  [Help] Tại sao ado recordset không cho sửa thucgia 5 635 15-10-15, 11:46 PM
Bài mới nhất: thucgia

Chuyển nhanh:


User(s) browsing this thread: 1 Guest(s)
Diễn Đàn Thơ Văn Thi Ẩm Lâu|Nhà Hàng Sông Thơ