Entity Framework and Transaction Scope (LINQ, Entity Framework) |
Entity Framework and Try Catch Exception (LINQ, Entity Framework) การใช้งาน Transaction Scope ค่อนข้างจะมีความสำคัญกับ Application ที่ต้องการความถูกต้องของการทำงาน โดยเมื่อมีการเรียกใช้งาน Transaction รายการข้อมูลที่ Insert, Update และ Delete จะยังอยู่แค่ใน Temp ยังไม่ได้มีการกระทำลงใน Table จริง ๆ ทั้งนี้เมื่อมีการ Error เกิดขึ้นในขั้นตอนใดขั้นตอนหนึ่ง เราสามารถที่จะยกเลิกรายการ (Rollback) ข้อมูลทั้งหมดที่กระทำลงไป หรือในกรณีที่โปรแกรมทำงานราบรื่นไม่มีข้อผิดพลาดใด ๆ เกิดขึ้นก็ให้โปรแกรม Commit ข้อมูลถือว่าเป็นการเสร็จสิ้นกระบวนการใช้ Transaction
ในการใช้ Transaction เมื่อมีการ Open Transaction แล้ว และตามด้วยเปิด Connection รายการกระทำกับข้อมูลหลังจากนี้ จะต้องอยู่ภายใต้ Connection ตัวเดียวกัน ในเคสนี้เราจะเปิด Connection ได้แค่ครั้งเดียวเท่านั้น จะไม่สามารถเปิด Connection ขึ้นมาได้ ฉะนั้นในกรณ๊ที่มี Method ย่อยอื่น ๆ ที่เรียกใช้ Entity เราจะต้องทำการส่งค่า Connection นี้ไปใช้งานใน Method นั้น ๆ ด้วย
Note!! เป็นข้อข้องใจของใครหลาย ๆ คนว่าในกรณีที่ใช้ Transaction เมื่อเกิดการ Insert , Update และ Delete ซึ่งจะยังไม่มีการ Commit ข้อมูลลงใน Table จริง ๆ แล้วในกรณีที่เกิด Query หลังจากนั้น เช่น ใน Transaction มีการแก้ไขข้อมูลนั้น ๆ ไปแล้ว แล้วใน Statement ถัดมามีการ Query ข้อมูลนั้นมาใช้ มันจะเป็นข้อมูลก่อนการแก้ไข หรือ เป็นข้อมูลที่ถูกแก้ไขในระหว่างการทำงานของ Transaction
คำตอบคือ!! เป็นข้อมูลใหม่ที่เกิดในช่วงระหว่าง Transaction นั่นหมายถึงว่าใน Transaction มีการกระทำอะไรลงไป แม้ยังไม่ได้มีการ Commit เมื่อเรา Query ข้อมูลช่วงนั้น ๆ กลับมาใช้ใหม่ ก็จะได้ข้อมูลใหม่ที่เกิดในช่วง Transaction
Transaction Scope Syntax (C#)
using (TransactionScope tran = new TransactionScope())
{
// Create new entities from Entities
using (var db = new myDatabaseEntities())
{
db.Database.Connection.Open();
try
{
// Statement
// Statement
// Statement
db.SaveChanges();
tran.Complete();
}
catch (Exception ex)
{
// ex.InnerException.InnerException.Message
}
finally
{
db.Database.Connection.Close();
db.Dispose();
tran.Dispose();
}
}
}
Transaction Scope Syntax (VB.Net)
Using tran As New TransactionScope()
' Create new entities from Entities
Using db = New myDatabaseEntities()
db.Database.Connection.Open()
Try
' Statement
' Statement
' Statement
db.SaveChanges()
tran.Complete()
' ex.InnerException.InnerException.Message
Catch ex As Exception
Finally
db.Database.Connection.Close()
db.Dispose()
tran.Dispose()
End Try
End Using
End Using
Example 1 : การ Insert ข้อมูลแบบปกติโดยไม่ใช่ Transaction
ใน Table มีข้อมูลของ C006 อยู่แล้ว แต่จะลอง Insert ข้อมูลใหม่โดยมี C005 และ C006
Code (C#)
private void frmMain_Load(object sender, EventArgs e)
{
// Create new entities from Entities
using (var db = new myDatabaseEntities())
{
try
{
// Insert Statement 1
db.CUSTOMER.Add(new CUSTOMER()
{
CUSTOMER_ID = "C005",
NAME = "Rut Wisarut",
EMAIL = "[email protected]",
COUNTRY_CODE = "TH",
BUDGET = 5000000,
USED = 0,
});
db.SaveChanges();
// Insert Statement 2
db.CUSTOMER.Add(new CUSTOMER()
{
CUSTOMER_ID = "C006",
NAME = "Fun Wipa",
EMAIL = "[email protected]",
COUNTRY_CODE = "UK",
BUDGET = 7000000,
USED = 0,
});
db.SaveChanges();
}
catch (DataException ex)
{
MessageBox.Show(ex.InnerException.InnerException.Message);
}
}
}
Code (VB.Net)
Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' Create new entities from Entities
Using db = New myDatabaseEntities()
Try
' Insert Statement 1
db.CUSTOMER.Add(New CUSTOMER() With { _
.CUSTOMER_ID = "C005", _
.NAME = "Rut Wisarut", _
.EMAIL = "[email protected]", _
.COUNTRY_CODE = "TH", _
.BUDGET = 5000000, _
.USED = 0 _
})
db.SaveChanges()
' Insert Statement 2
db.CUSTOMER.Add(New CUSTOMER() With { _
.CUSTOMER_ID = "C006", _
.NAME = "Fun Wipa", _
.EMAIL = "[email protected]", _
.COUNTRY_CODE = "UK", _
.BUDGET = 7000000, _
.USED = 0 _
})
db.SaveChanges()
Catch ex As DataException
MessageBox.Show(ex.InnerException.InnerException.Message)
End Try
End Using
End Sub
Screenshot
แสดง Error ในขณะที่กำลังทำงาน
แต่จะเห็นว่าในขณะนี้โปรแกรม Error มีการ Insert ข้อมูลลงไปใน 1 รายการ
Example 2 : การ Insert ข้อมูลโดยใช้ Transaction Scope
Add Reference ของ System.Transaction เข้ามาใน Project
ในการเรียกใช้งาน Transaction จะต้องทำการ using หรือ Import ตัว System.Transactions
Code (C#)
private void frmMain_Load(object sender, EventArgs e)
{
using (TransactionScope tran = new TransactionScope())
{
// Create new entities from Entities
using (var db = new myDatabaseEntities())
{
db.Database.Connection.Open();
try
{
// Insert Statement 1
db.CUSTOMER.Add(new CUSTOMER()
{
CUSTOMER_ID = "C005",
NAME = "Rut Wisarut",
EMAIL = "[email protected]",
COUNTRY_CODE = "TH",
BUDGET = 5000000,
USED = 0,
});
// Insert Statement 2
db.CUSTOMER.Add(new CUSTOMER()
{
CUSTOMER_ID = "C006",
NAME = "Fun Wipa",
EMAIL = "[email protected]",
COUNTRY_CODE = "UK",
BUDGET = 7000000,
USED = 0,
});
db.SaveChanges();
tran.Complete();
}
catch (Exception ex)
{
MessageBox.Show(ex.InnerException.InnerException.Message);
}
finally
{
db.Database.Connection.Close();
db.Dispose();
tran.Dispose();
}
}
}
}
Code (VB.Net)
Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Using tran As New TransactionScope()
' Create new entities from Entities
Using db = New myDatabaseEntities()
db.Database.Connection.Open()
Try
' Insert Statement 1
db.CUSTOMER.Add(New CUSTOMER() With { _
.CUSTOMER_ID = "C005", _
.NAME = "Rut Wisarut", _
.EMAIL = "[email protected]", _
.COUNTRY_CODE = "TH", _
.BUDGET = 5000000, _
.USED = 0 _
})
' Insert Statement 2
db.CUSTOMER.Add(New CUSTOMER() With { _
.CUSTOMER_ID = "C006", _
.NAME = "Fun Wipa", _
.EMAIL = "[email protected]", _
.COUNTRY_CODE = "UK", _
.BUDGET = 7000000, _
.USED = 0 _
})
db.SaveChanges()
tran.Complete()
Catch ex As Exception
MessageBox.Show(ex.InnerException.InnerException.Message)
Finally
db.Database.Connection.Close()
db.Dispose()
tran.Dispose()
End Try
End Using
End Using
End Sub
Screenshot
จากตัวอย่างใน Example 2 นี้จะมีการใช้ Transaction มาควบคุมการทำงาน ซึ่งในเคสนี้จะมี Error และการ Insert ข้อมูลที่ได้ Insert ไปแล้วนั้นจะไม่มีการ Commit ลงใน Table
ของแถม ตัวอย่างนี้จะมีในส่วนของ Entity Framework กับ Transaction และการใช้คำสั่ง SqlConnection โดยเรียกใช้ Connection ของ Entity Framework และการใช้ Transaction ของ SqlConnection ซึ่งทั้ง 2 Transaction นี้จะใช้ Connection ตัวเดียวกัน
Code (C#)
private void frmMain_Load(object sender, EventArgs e)
{
using (TransactionScope tran = new TransactionScope())
{
// Create new entities from Entities
using (var db = new myDatabaseEntities())
{
db.Database.Connection.Open();
EntityConnection ec = (EntityConnection)db.Database.Connection;
SqlConnection sqlCon = (SqlConnection)ec.StoreConnection;
SqlTransaction sqlTrans = sqlCon.BeginTransaction();
try
{
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(sqlCon, SqlBulkCopyOptions.Default, sqlTrans))
{
// Statement
}
// ExecuteNonQuery
string strSQL = "INSERT INTO customer (CustomerID,Name,Email,CountryCode,Budget,Used) " +
" VALUES ('C005','Weerachai Nukitram','[email protected]','TH','2000000','1000000')";
SqlCommand objCmd = new SqlCommand();
objCmd.Connection = sqlCon;
objCmd.CommandType = CommandType.Text;
objCmd.CommandText = strSQL;
objCmd.ExecuteNonQuery();
// Insert Statement 2
db.CUSTOMER.Add(new CUSTOMER()
{
CUSTOMER_ID = "C006",
NAME = "Fun Wipa",
EMAIL = "[email protected]",
COUNTRY_CODE = "UK",
BUDGET = 7000000,
USED = 0,
});
db.SaveChanges();
tran.Complete();
sqlTrans.Commit();
}
catch (Exception ex)
{
MessageBox.Show(ex.InnerException.InnerException.Message);
}
finally
{
db.Database.Connection.Close();
db.Dispose();
tran.Dispose();
sqlTrans.Dispose();
}
}
}
}
Code (VB.Net)
Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Using tran As New TransactionScope()
' Create new entities from Entities
Using db = New myDatabaseEntities()
db.Database.Connection.Open()
Dim ec As EntityConnection = DirectCast(db.Database.Connection, EntityConnection)
Dim sqlCon As SqlConnection = DirectCast(ec.StoreConnection, SqlConnection)
Dim sqlTrans As SqlTransaction = sqlCon.BeginTransaction()
Try
' Statement
Using bulkCopy As New SqlBulkCopy(sqlCon, SqlBulkCopyOptions.[Default], sqlTrans)
End Using
' ExecuteNonQuery
Dim strSQL As String = "INSERT INTO customer (CustomerID,Name,Email,CountryCode,Budget,Used) " + " VALUES ('C005','Weerachai Nukitram','[email protected]','TH','2000000','1000000')"
Dim objCmd As New SqlCommand()
objCmd.Connection = sqlCon
objCmd.CommandType = CommandType.Text
objCmd.CommandText = strSQL
objCmd.ExecuteNonQuery()
' Insert Statement 2
db.CUSTOMER.Add(New CUSTOMER() With { _
.CUSTOMER_ID = "C006", _
.NAME = "Fun Wipa", _
.EMAIL = "[email protected]", _
.COUNTRY_CODE = "UK", _
.BUDGET = 7000000, _
.USED = 0 _
})
db.SaveChanges()
tran.Complete()
sqlTrans.Commit()
Catch ex As Exception
MessageBox.Show(ex.InnerException.InnerException.Message)
Finally
db.Database.Connection.Close()
db.Dispose()
tran.Dispose()
sqlTrans.Dispose()
End Try
End Using
End Using
End Sub
ในการเรียกใช้งาน Transaction จะต้องทำการ using หรือ Import ตัว System.Transactions , System.Data.SqlClient และ System.Data.EntityClient
|
ช่วยกันสนับสนุนรักษาเว็บไซต์ความรู้แห่งนี้ไว้ด้วยการสนับสนุน Source Code 2.0 ของทีมงานไทยครีเอท
|
|
|
By : |
ThaiCreate.Com Team (บทความเป็นลิขสิทธิ์ของเว็บไทยครีเอทห้ามนำเผยแพร่ ณ เว็บไซต์อื่น ๆ) |
|
Score Rating : |
|
|
|
Create/Update Date : |
2015-10-02 21:18:20 /
2017-03-24 22:55:42 |
|
Download : |
No files |
|
Sponsored Links / Related |
|
|
|
|
|