• Tại sao Ado recordset inner join readonly
  • Tại sao Ado recordset inner join readonly

    thucgia > 18-10-15, 01:12 PM

    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
  • RE: Tại sao Ado recordset inner join readonly

    ongke0711 > 18-10-15, 02:00 PM

    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" 
  • RE: Tại sao Ado recordset inner join readonly

    thucgia > 18-10-15, 02:18 PM

    (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é.
  • RE: Tại sao Ado recordset inner join readonly

    thucgia > 18-10-15, 03:06 PM

    (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.
  • RE: Tại sao Ado recordset inner join readonly

    Minh Tiên > 23-10-15, 09:46 PM

    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./.
  • RE: Tại sao Ado recordset inner join readonly

    thucgia > 24-10-15, 12:15 AM

    (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
  • RE: Tại sao Ado recordset inner join readonly

    MTNQ > 25-10-15, 03:59 AM

    (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
  • RE: Tại sao Ado recordset inner join readonly

    thucgia > 25-10-15, 12:13 PM

    (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
  • RE: Tại sao Ado recordset inner join readonly

    MTNQ > 27-10-15, 02:17 AM

    (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
  • RE: Tại sao Ado recordset inner join readonly

    thucgia > 27-10-15, 02:03 PM

    (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ả?