項目同時存在 EF DbContext 與 LINQ to SQL DataContext 兩套 ORM,調用同一存儲過程 uspUpdateEmployeeLogin(6 參數),API 差異巨大,易踩坑。
using (var ctx = new AdventureWorks2014Entities()) {
int ret = ctx.Database.ExecuteSqlCommand(
"EXEC [HumanResources].[uspUpdateEmployeeLogin] " +
"@BusinessEntityID, @OrganizationNode, @LoginID, @JobTitle, @HireDate, @CurrentFlag",
new SqlParameter("@BusinessEntityID", 10),
new SqlParameter("@OrganizationNode", DBNull.Value),
new SqlParameter("@LoginID", @"adventure-works\michael6"),
new SqlParameter("@JobTitle", "Research and Development Manager23"),
new SqlParameter("@HireDate", DateTime.Now),
new SqlParameter("@CurrentFlag", true)
);
}
SqlParameter 自動處理類型轉換、NULL 值、SQL 注入防護。@ 可不帶,EF 內部匹配。ExecuteSqlCommand 返回受影響行數;需返回結果集用 SqlQuery。using (var ctx = new AWDataClassesDataContext()) {
// 必須手動拼接 SQL 字符串,參數內插
string sql = string.Format(
"EXEC [HumanResources].[uspUpdateEmployeeLogin] " +
"@BusinessEntityID={0}, @OrganizationNode={1}, @LoginID=N'{2}', @JobTitle=N'{3}', @HireDate=N'{4}', @CurrentFlag=N'{5}'",
10, "NULL", @"adventure-works\michael6", "Research and Development Manager12",
DateTime.Now.ToString(), true.ToString()
);
int ret = ctx.ExecuteCommand(sql);
}
ExecuteCommand 僅接受格式化字符串,參數為 object[] 但實測不支持 DBNull.Value、日期格式化極易出錯。if-else 拼接 NULL 或 N'value',代碼極其醜陋。| 維度 | EF DbContext | LINQ to SQL DataContext |
|---|---|---|
| 參數綁定 | SqlParameter 強類型 | 字符串格式化/弱類型 object[] |
| NULL 處理 | DBNull.Value 原生支持 | 手寫 "NULL" 字符串 |
| 日期類型 | 自動格式化 | ToString() 依賴當前文化 |
| SQL 注入防護 | 參數化查詢,天然免疫 | 無,極高風險 |
| 存儲過程映射 | Function Import → 強類型方法 | 設計器拖拽生成方法(舊、難維護) |
| 維護狀態 | 活躍開發、.NET Core 全支持 | 微軟宣布停止更新、僅維護關鍵補丁 |
FromSqlRaw/ExecuteSqlRaw + 參數化。LINQ to SQL 設計器生成的 500+ 表實體類已成技術債,手動拼接 SQL 調用存儲過程是「以毒攻毒」。EF 的參數化機制、類型安全、現代化生態,是遷移的必然選擇。盡早制定遷移路線圖,停止在 LINQ to SQL 上投入新代碼。