顯示具有 SQL Server 標籤的文章。 顯示所有文章
顯示具有 SQL Server 標籤的文章。 顯示所有文章

SQL Server 連線共用的問題

0 comments
在預設的情況下,SQL Server 的 .NET Framework 資料提供者會自動提供連線共用(Connection Pooling),以利提升應用程式的延展性及效能。然而,當 ADO.NET 用戶端嘗試使用共用連線時,有可能會遇到如下的例外狀況:
在傳送要求至伺服器時發生傳輸層級的錯誤。 (provider: TCP 提供者, error: 0 - 遠端主機已強制關閉一個現存的連線。)

A transport-level error has occurred when sending the request to the server. (provider: TCP Provider, error: 0 - An existing connection was forcibly closed by the remote host.)

如果共用連線集區的可用連線與伺服器的連接已嚴重損毀,例如:伺服器重新啟動、容錯移轉、使用者處理序被刪除等,連線共用器並無法立即發現異常,直到將其傳回至 ADO.NET 呼叫端並嘗試與伺服器進行通訊後,才會偵測到連接已損毀。當發生此情況時,連線共用器會從集區中移除該連線,並且擲回如上的例外狀況。

連線共用機制並非能完全保證可用連線的有效性,除非你在連線字串中指定 Pooling=false 明確停用,否則你難以避免此類問題發生。除此之外,建議你在資料存取程式碼中加入例外處理常式因應,或是使用 Retryer Pattern 做最佳的容錯處理。

參考資料:
SQL Server 連接共用 (ADO.NET)

繼續閱讀...

Problem Using INSTEAD OF Triggers with Entity Framework

0 comments
若你在使用識別資料行做為主索引鍵的資料表中,定義 INSTEAD OF INSERT 觸發程序,並透過 ObjectContext 的 SaveChanges 方法新增資料時,將會引發 OptimisticConcurrencyException,並導致整個交易復原。以下是發生例外狀況的錯誤訊息:
存放區更新、插入或刪除陳述式影響到非預期數目的資料列 (0)。這些實體載入之後可能被修改或刪除了。請重新整理 ObjectStateManager 實體。

Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries.

如以下範例,會依據 AdventureWorks 實體資料模型的定義,將新的實體物件附加到物件內容:
using (AdventureWorksEntities context = new AdventureWorksEntities()) 
{
context.AddToSalesReason(new SalesReason() {
Name = "Recommendation", ReasonType = "Other", ModifiedDate = DateTime.Now
});
context.SaveChanges();
}

當呼叫 SaveChanges 方法時,物件服務會產生及執行以下 SQL 命令:
exec sp_executesql N'insert [Sales].[SalesReason]([Name], [ReasonType], [ModifiedDate])
values (@0, @1, @2)
select [SalesReasonID]
from [Sales].[SalesReason]
where @@ROWCOUNT > 0 and [SalesReasonID] = scope_identity()
'
,N'@0 nvarchar(14),@1 nvarchar(5),@2 datetime2(7)'
,@0=N'Recommendation',@1=N'Other',@2='2009-11-02 15:14:54.4856524'

因為該實體物件包含識別插入的實體索引鍵,所以會在 INSERT 陳述式後,搭配使用 SCOPE_IDENTITY 函數以取得插入識別欄位中的最後一個識別值。然而,如果此資料表已定義 INSTEAD OF INSERT 觸發程序,則 SCOPE_IDENTITY 函數會因為分屬不同的範圍(Scope)而傳回 NULL 值,於是導致 SaveChanges 失敗,而復原該筆交易並擲回如前述的 OptimisticConcurrencyException 例外狀況。

要解決這個問題,你可以使用預儲程序取代 INSTEAD OF INSERT 觸發程序,然後利用實體資料模型設計工具(Entity Designer),把實體類型的修改函式對應至預存程序。或者,你也可以使用 ExecuteCommand 擴充方法來直接執行新增作業的預儲程序。

繼續閱讀...