LINQ To SQL與Transaction

 
LINQ To SQL Transaction
 
/ 黃忠成
 
  不管你是由我的書中,或是MSDN、網站處得知,LINQ to SQL之DataContext於SubmitChanges函式執行時,就算不指定Transaction,DataContext都會自動啟動一個Transaction,在許多ORM中,這算是相當常見的設計。
 不過,如果我不想要這個預設的Transaction呢?原因有很多,可能是為了減少Lock的時間,或是效能、資源等等,反正就是不想要這個預設行為就是了!只要簡簡單單的更新資料就好了。
 可能嗎?就目前的LINQ To SQL設計來說,這個行為是強制性的,且無可調整之空間,但!若要強渡關山也不是沒交通工具,DataContext開了一個小口,讓我們可以覆載SubmitChanges函式,以此為起點,我利用了大量的Reflection技巧,讓Transaction消失。
using System;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Collections.Generic;
using System.Linq;
using System.Data.Linq;
using System.Text;
using System.Reflection;
 
namespace ConsoleApplication35
{
    class Program
    {
        static void Main(string[] args)
        {
            NorthwindDataContext context = new NorthwindDataContext();           
            var item = (from s1 in context.Customers where s1.CustomerID == "VINET"
                        select s1).FirstOrDefault();
            if (item != null)
                item.ContactName = "VINET14";
            Console.ReadLine();
            context.DisableTransaction = true;
            context.SubmitChanges();
            Console.ReadLine();
        }
    }
 
    partial class NorthwindDataContext
    {
        public bool DisableTransaction { get; set; }
 
        private static MethodInfo _checkDispose = null;
        private static MethodInfo _checkNotInSubmitChanges = null;       
        private static MethodInfo _verifyTrackingEnabled = null;
        private static MethodInfo _acceptChanges = null;
        private static MethodInfo _submitChanges = null;
        private static FieldInfo _conflicts = null;
        private static FieldInfo _isInSubmitChanges = null;
        private static PropertyInfo _services = null;
        private static Type _changeProcessorType = null;
        private static ConstructorInfo _ci = null;
 
        static NorthwindDataContext()
        {
            _checkDispose = typeof(DataContext).GetMethod("CheckDispose",
                         BindingFlags.NonPublic | BindingFlags.Instance);
            _checkNotInSubmitChanges =
               typeof(DataContext).GetMethod("CheckNotInSubmitChanges",
                      BindingFlags .NonPublic | BindingFlags.Instance);
            _verifyTrackingEnabled = typeof(DataContext).GetMethod("VerifyTrackingEnabled",
                                      BindingFlags.NonPublic | BindingFlags.Instance);
            _acceptChanges = typeof(DataContext).GetMethod("AcceptChanges",
                             BindingFlags.NonPublic | BindingFlags.Instance);
            _conflicts = typeof(DataContext).GetField("conflicts",
                              BindingFlags.NonPublic | BindingFlags.Instance);
            _isInSubmitChanges = typeof(DataContext).GetField("isInSubmitChanges",
                                 BindingFlags.NonPublic | BindingFlags.Instance);
            _changeProcessorType = typeof(DataContext).Assembly.GetType(
                             "System.Data.Linq.ChangeProcessor");
            _services = typeof(DataContext).GetProperty("Services",
                        BindingFlags.NonPublic | BindingFlags.Instance);
            _ci = _changeProcessorType.GetConstructor(
                       BindingFlags.NonPublic | BindingFlags.Instance, null,
                      new Type[]                      
            { typeof(DataContext).Assembly.GetType("System.Data.Linq.CommonDataServices"),
              typeof(DataContext) }, null);
            _submitChanges = _changeProcessorType.GetMethod("SubmitChanges",
                     BindingFlags.NonPublic | BindingFlags.Instance);
        }
 
        public override void SubmitChanges(System.Data.Linq.ConflictMode failureMode)       
        {
            if (DisableTransaction)
            {
                _checkDispose.Invoke(this, null);
                _checkNotInSubmitChanges.Invoke(this, null);
                _verifyTrackingEnabled.Invoke(this, null);
                ((ChangeConflictCollection)_conflicts.GetValue(this)).Clear();
                try
                {
                    _isInSubmitChanges.SetValue(this, true);
                    object processor = _ci.Invoke(new object[]
                             { _services.GetValue(this, null), this });
                    _submitChanges.Invoke(processor, new object[] { failureMode });
                    _acceptChanges.Invoke(this, null);
                }
                finally
                {
                    _isInSubmitChanges.SetValue(this, false);
                }
            }
            else
                base.SubmitChanges(failureMode);
        }
    }
}
當DisableTransaction屬性為False時,SQL Profiler的畫面如下:
當設定DisableTransaction為True時,你會發現Transaction未被啟動。
處理完畢,我個人是覺得,LINQ To SQL應該把Transaction以Session概念處理,如Hibernate。
 
### 解决Windows系统中特定文件夹名称出现乱码 当遇到Windows系统中的文件夹名称显示为乱码时,通常是因为字符编码不匹配所引起的。为了有效解决问题,可以从以下几个方面着手: 对于已经存在的乱码文件夹名,在尝试修改前建议先备份重要数据以防意外情况发生。 如果问题是由于网络下载或跨操作系统传输引起,则可能涉及到不同操作系统的默认编码差异。例如,中文Windows系统的默认字符集通常是CP936 (GBK)[^3];而Linux系统则更倾向于使用UTF-8作为标准编码方式[^2]。因此,在处理这类问题时需要注意源和目标环境之间的编码转换。 #### 方法一:通过命令提示符更改文件夹名字 可以通过命令行工具来修正这些乱码文件夹的名字。打开“运行”,输入`cmd`启动命令提示符窗口,并切换至含有乱码文件夹的位置。之后利用`ren`指令重新命名受影响的对象。假设有一个名为“?????.txt”的文本档以及一个叫作“????”的目录存在乱码现象,那么可以执行如下命令来进行修复: ```batch ren "C:\path\to\bizarre_folder_name" 正确的新文件夹名称 ``` 请注意路径应替换为实际位置,并确保新给定的名字符合预期的语言文字形式。 #### 方法二:调整区域选项设置 有时,适当调整计算机上的地区与语言设定也能帮助解决部分因本地化配置不当而导致的问题。进入控制面板 -> 时钟和区域 -> 更改日期、时间或数字格式 -> 高级设置页面内可找到有关非Unicode程序使用的默认代码页选项。将其设为适合当前工作所需的文字编码(如简体中文对应于GB2312),这有助于改善某些应用程序读取外部资源时的表现[^1]。 #### 方法三:第三方软件辅助 除了上述内置手段外,还可以借助专门设计用于批量重命名单元格内容的应用程序,像Bulk Rename Utility这样的免费实用程序提供了直观界面让用户轻松完成复杂的重命名任务[^5]。不过这种方法更适合用来预防未来可能出现的相似状况而非直接纠正现有的错误记录。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值