แต่ แก้ไข Record แรก แล้วบันทึก มันไม่ยอมบันทึกครับ
แต่ ถ้าแก้ไข Record อีก 1 Record (ต่อจากบรรทัดบน) พอกดเซฟ Record นี้ Record บรรทัดบน จะบันทึก แต่ Record ที่กดบันทึกล่าสุดไม่ยอมบันทึกนะครับ
จะเป็นแบบนี้ คือ แก้ไขข้อมูล 10 record จะบันทึก แค่ 1-9 ผมเลยงงว่าทำไม
ปัญหาที่เกิดคือ จากโค้ดนี้ มันอับเดทได้
- กดแก้ไข record "A" กด save (ไม่บันทึก)
- กดแก้ไข record "B" กด save (ดันบันทึก A แต่ว่าไม่บันทึก B)
- กดแก้ไข record "C" ต่อ แล้วกด save (ก็บันทึก B แต่ไม่บันทึก C)
Private com1 As New OdbcConnection(con)
Private adpt As New OdbcDataAdapter("SELECT * FROM tbproduct_file", com1)
Private ds As New DataTable
Private cmdBuilder As OdbcCommandBuilder
Private Sub frmProductDescription_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Try
GenGridView()
cmdBuilder = New OdbcCommandBuilder(adpt)
adpt.InsertCommand = cmdBuilder.GetInsertCommand
adpt.UpdateCommand = cmdBuilder.GetUpdateCommand
adpt.DeleteCommand = cmdBuilder.GetDeleteCommand
adpt.Fill(ds)
DataGridView1.DataSource = ds
Me.WindowState = FormWindowState.Maximized
Catch ex As Exception
Me.Text = "รายละเอียดสินค้า : " & ex.Message
Exit Sub
End Try
End Sub
Sub SaveDataProduct()
Try
Dim i As Integer
i = DataGridView1.CurrentRow.Index
DataGridView1.Item(1, i).Value = txtinternalcode.Text
DataGridView1.Item(3, i).Value = txtdescription.Text
DataGridView1.Item(4, i).Value = txtshortdesc.Text
DataGridView1.Item(5, i).Value = txtunit.Text
DataGridView1.Item(6, i).Value = txtgroup1.Text
DataGridView1.Item(10, i).Value = txtvattype.Text
DataGridView1.Item(11, i).Value = txtproducttype.Text
DataGridView1.Item(13, i).Value = txtcosttype.Text
If CheckBox1.Checked = True Then DataGridView1.Item(9, i).Value = 1
If CheckBox1.Checked = False Then DataGridView1.Item(9, i).Value = 0
'MsgBox(DataGridView1.Rows.Count())
adpt.Update(ds)
MsgBox("บันทึกข้อมูลสำเร็จ", MsgBoxStyle.OkOnly, "OK")
Catch ex As Exception
Me.Text = "รายละเอียดสินค้า : บันทึกข้อมูล Error : " & ex.Message
End Try
End Sub
MsgBox("บันทึกข้อมูลสำเร็จ", MsgBoxStyle.OkOnly, "OK")
Catch ex As Exception
Me.Text = "รายละเอียดสินค้า : บันทึกข้อมูล Error : " & ex.Message
End Try
End Sub
USE [xDB]
GO
/****** Object: StoredProcedure [dbo].[xGen] Script Date: 10/15/1900 12:52:58 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: โชคไม่เคยเข้าข้าง (กู)
-- Create date: 1900-07-10
-- Description:
-- =============================================
ALTER PROCEDURE [dbo].[ClassGen]
-- Add the parameters for the stored procedure here
@p1 int = 0,
@p2 int = 0
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
declare @field table (fieldname varchar(50), fieldtype varchar(50))
declare @table_name varchar(50)
set @table_name = 'msrUsers' -- this is the table name
insert into @field
Select sc.name, st.name
from
sysobjects so,
syscolumns sc,
systypes st
where
so.id = sc.id
and so.xtype = 'U'
and so.name = @table_name
and st.xtype = sc.xtype
print 'Public Class ' + @table_name
declare @fieldname varchar(50)
declare @fieldtype varchar(50)
declare @constructor varchar(500)
declare @assign varchar(500)
declare cur cursor for
select fieldname, fieldtype
from @field
open cur
fetch next from cur
into @fieldname, @fieldtype
set @constructor = ''
set @assign = ''
while @@fetch_status = 0
begin
set @fieldtype = case @fieldtype
when 'int' then 'Integer'
when 'smallint' then 'Int16'
when 'tinyint' then 'Short'
when 'varchar' then 'String'
when 'nvarchar' then 'String'
when 'bit' then 'Boolean'
when 'float' then 'Double'
when 'datetime' then 'DateTime'
else @fieldtype
end
set @constructor = @constructor + 'ByVal v' + @fieldname + ' AS ' + @fieldtype + ', '
set @assign = @assign + '_' + @fieldname + ' = v' + @fieldname + ' : '
print ''
print 'Private _' + @fieldname + ' AS ' + @fieldtype
print 'Public Property ' + @fieldname + '() AS ' + @fieldtype
print ' Get'
print ' return _' + @fieldname
print ' End Get'
print ' Set (value AS ' + @fieldtype + ')'
print ' _' + @fieldname + ' = value'
print ' End Set'
print 'End Property'
print ''
fetch next from cur
into @fieldname, @fieldtype
end
print 'Public Sub New(' + substring(@constructor, 0, len(@constructor)) + ')'
print ' ' + substring(@assign, 0, len(@assign) -1)
print 'End Sub'
print 'End Class'
END
USE tempdb
GO
IF OBJECT_ID(N'tempdb..#A') IS NULL --IS NOT NULL
BEGIN
CREATE TABLE #A (ID int)
INSERT INTO #A VALUES (1), (2), (3)
END
SELECT * FROM #A
IF OBJECT_ID(N'tempdb..#B') IS NULL --IS NOT NULL
BEGIN
CREATE TABLE #B (ID int)
INSERT INTO #B VALUES (2), (3), (4)
END
SELECT * FROM #B
/*
DECLARE #A TABLE (ID int)
DECLARE #B TABLE (ID int)
INSERT INTO #A VALUES (2),(3),(4)
INSERT INTO #B VALUES (2),(3),(4)
*/
SELECT * FROM #A x FULL OUTER JOIN #B y ON x.ID = y.ID
/*----------- -----------
1 NULL
2 2
3 3
NULL 4
(4 row(s) affected)
*/
SELECT * FROM #A x JOIN #B y ON x.ID = y.ID
/*----------- -----------
2 2
3 3
(2 row(s) affected)
*/
SELECT * FROM #A x CROSS JOIN #B y
/*----------- -----------
1 2
2 2
3 2
1 3
2 3
3 3
1 4
2 4
3 4
(9 row(s) affected)
*/
/*
That is not legal because A.Val is out of scope within the derived table;
this is because the derived table is evaluated independently of the other tables in the SELECT.
To limit the rows in table B so that B.Val = A.Val,
we must do that outside of the derived table via a join or in the criteria
SELECT * FROM #A a CROSS JOIN (SELECT x.ID FROM #B x WHERE x.ID = a.ID) b
*/
SELECT a.*, b.* FROM #A a CROSS JOIN (SELECT * FROM #B) b
WHERE a.ID = b.ID
/*
----------- -----------
2 2
3 3
(2 row(s) affected)
*/
/*
Summary : Full Outer Join
all matching rows (inner join) + all rows from A not matching B
+ all rows from B not matching A
(it applies actually a left and a right join at the same time)
*/
/*
Summary : Cross Join
is a cartesian product, so this will in fact combine all rows from A with all rows from B
*/
/*OK Finally
cross join is a*b rows,
full outer join gives matched and unmatched rows
*/
SELECT #A.*, b.* FROM #A CROSS APPLY (SELECT #B.ID FROM #B ) b
SELECT * FROM #A CROSS APPLY (SELECT TOP 1 * FROM #B ORDER BY ID DESC) b
/*
SELECT #A.*, b.ID FROM #A CROSS JOIN (SELECT #B.ID FROM #B WHERE #B.ID = #A.ID) b
Msg 4104, Level 16, State 1, Line 1
The multi-part identifier "#A.ID" could not be bound.
*/
SELECT #A.*, b.ID FROM #A CROSS APPLY (SELECT #B.ID FROM #B WHERE #B.ID = #A.ID) b
-- CROSS APPLY also allows us to quickly get columns from the "previous" row
-- in a table quite easily:
SELECT a.*, Prev.*
FROM #A a
CROSS APPLY
(
SELECT TOP 1 * FROM #A p
WHERE p.ID < a.ID ORDER BY ID DESC
) Prev
/*
Note that the above CROSS APPLY will not return
any orders without a previous order;
we would use OUTER APPLY to ensure that all orders are returned even
if no previous orders exist:
*/
SELECT a.*, Prev.*
FROM #A a
OUTER APPLY
(
SELECT TOP 1 * FROM #A p
WHERE p.ID < a.ID ORDER BY ID DESC
) Prev
IF OBJECT_ID(N'tempdb..#A') IS NOT NULL
BEGIN
DECLARE @ValueA int;
END
IF OBJECT_ID(N'tempdb..#B') IS NOT NULL
BEGIN
DECLARE @ValueB int;
END
Public Shared Function Write2Database(ByVal BranchID As Integer, ByVal sysID As Short,
ByVal MenuID As Integer, ByVal ErrorAction As String,
ByVal ErrorDescription As String, ByVal ErrorDateTime As DateTime,
ByVal ErrorUserID As Integer, ByVal ErrorIPAddress As String) As Boolean
Dim suc As Boolean = False
Try
Dim value As New List(Of WL_Model.sysErrorLog) From {New WL_Model.sysErrorLog With {.BranchID = BranchID,
.sysID = sysID,
.MenuID = MenuID,
.ErrorAction = ErrorAction,
.ErrorDescription = ErrorDescription,
.ErrorDateTime = ErrorDateTime,
.ErrorUserID = ErrorUserID,
.ErrorIPAddress = ErrorIPAddress
}
}
WL_Database.WL_SQLHelperExt.SetData(WL_BLL.sysErrorLog.SetInsertCommand(value))
suc = True
Catch ex As Exception
'Write Error log.
End Try
Return suc
End Function
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
'2012-03-24 Support Windows Client & All Application. example delphi, visual foxpro, etc
If Request.QueryString("UserName") <> Nothing AndAlso Request.QueryString("Password") <> Nothing Then
Dim strUserName As String = Request.QueryString("UserName") '***** byebye Decrypt
Dim strPassword As String = Request.QueryString("Password") '***** byebye Decrypt
' ******************************************************************************************
' Protect Decomplier Algorithm with C++ for Encrypt UserName and Password
' validation here and check the username and password in the database
' *******************************************************************************************
FormsAuthentication.Authenticate("นามคุณ", "รหัสผ่าน") 'Check in web.config with SHA1
FormsAuthentication.SetAuthCookie(strUserName, False, FormsAuthentication.FormsCookiePath)
FormsAuthentication.RedirectFromLoginPage(strUserName, False, FormsAuthentication.FormsCookiePath)
' Create cookie and return it
Dim ticket As New FormsAuthenticationTicket(1,
strUserName,
DateTime.Now,
DateTime.Now.AddDays(30),
False,
New Guid().ToString(),
FormsAuthentication.FormsCookiePath)
' Encrypt the ticket.
Dim encTicket As String = FormsAuthentication.Encrypt(ticket)
' Create the cookie.
Response.Write(encTicket)
Response.End()
Else
FormsAuthentication.SetAuthCookie("Guest", False) 'Test only XXX Remove this line in production
End If
End Sub
Public Function GetPurchaseNumber(Optional ByVal isOverLimit As Boolean = False)
Dim strWhere As String = If(isOverLimit, " WHERE (X.OverP1 > 0 Or X.OverP2 > 0)", String.Empty)
Dim x As String = <xsql>
;
WITH cte
AS (
SELECT *
,ROW_NUMBER() OVER (
ORDER BY InputType DESC
,StringNum ASC
) AS rn
FROM (
SELECT InputType
,StringNum
,LimitPrice1
,LimitPrice2
,Y.Price1
,Y.Price2
,ISNULL(LimitPrice1, 0) + ISNULL(Y.Price1, 0) AS OverP1
,ISNULL(LimitPrice2, 0) + ISNULL(Y.Price2, 0) AS OverP2
FROM GoodLuckConfigSpread AS Z
CROSS APPLY (
SELECT SUM(Price1) AS Price1
,SUM(Price2) AS Price2
FROM GoodLuck a
WHERE a.InputType = Z.InputType
AND a.StringNum = Z.StringNum
) Y
) X <%= strWhere %> --{0}
--WHERE X.OverP1 > 0
--OR X.OverP2 > 0
)
,cte0
AS (
SELECT InputType, MIN(rn) AS rn
FROM cte
GROUP BY InputType
)
,cte1
AS (
SELECT cte.InputType
,StringNum
,OverP1
,OverP2
,cte.rn
,Price1
,Price2
FROM cte0
CROSS JOIN cte WHERE cte0.InputType = cte.InputType AND (cte.rn -cte0.rn ) % 5 = 0
)
SELECT cte1.InputType
,cte1.StringNum AS StringNum_1
,cte1.Price1 AS Price1_1
,cte1.Price2 AS Price2_1
,cte1.OverP1 AS OverP1_1
,cte1.OverP2 AS OverP2_1
,cte2.StringNum AS StringNum_2
,cte2.Price1 AS Price1_2
,cte2.Price2 AS Price2_2
,cte2.OverP1 AS OverP1_2
,cte2.OverP2 AS OverP2_2
,cte3.StringNum AS StringNum_3
,cte3.Price1 AS Price1_3
,cte3.Price2 AS Price2_3
,cte3.OverP1 AS OverP1_3
,cte3.OverP2 AS OverP2_3
,cte4.StringNum AS StringNum_4
,cte4.Price1 AS Price1_4
,cte4.Price2 AS Price2_4
,cte4.OverP1 AS OverP1_4
,cte4.OverP2 AS OverP2_4
,cte5.StringNum AS StringNum_5
,cte5.Price1 AS Price1_5
,cte5.Price2 AS Price2_5
,cte5.OverP1 AS OverP1_5
,cte5.OverP2 AS OverP2_5
FROM cte1
LEFT JOIN cte AS cte2 ON cte1.InputType = cte2.InputType
AND cte2.rn - cte1.rn = 1
LEFT JOIN cte AS cte3 ON cte1.InputType = cte3.InputType
AND cte3.rn - cte1.rn = 2
LEFT JOIN cte AS cte4 ON cte1.InputType = cte4.InputType
AND cte4.rn - cte1.rn = 3
LEFT JOIN cte AS cte5 ON cte1.InputType = cte5.InputType
AND cte5.rn - cte1.rn = 4
</xsql>
Return Query(x.ToString())
End Function