【问题标题】:Why is SubSonic and ActiveRecord throwing an exception when updating a record?为什么 SubSonic 和 ActiveRecord 在更新记录时会抛出异常?
【发布时间】:2010-01-21 03:25:11
【问题描述】:

我在 MS SQL Server 2008 标准版中有下表:

CREATE TABLE [dbo].[NewTestQueue](
    [JobID] [int] IDENTITY(1,1) NOT NULL,
    [ServerName] [varchar](50) NULL,
    [DomainID] [int] NOT NULL,
    [Action] [varchar](50) NULL,
    [Folder] [varchar](150) NULL,
    [Method] [varchar](50) NULL,
    [ActionProfile] [varchar](50) NULL,
    [Title] [varchar](150) NULL,
    [Suffix] [varchar](50) NULL,
    [Host] [varchar](150) NULL,
    [Url] [varchar](250) NULL,
    [Expression] [varchar](50) NULL,
    [MasterTest] [varchar](50) NULL,
    [Completed] [bit] NOT NULL
) ON [PRIMARY]

我正在使用SubSonic ActiveRecord T4 模板,代码如下:

var tests = NewTestQueue.Find(d => !d.Completed);
foreach(var test in tests)
{
    // Do some work with test
    // ...

    // Now mark job as completed
    test.Completed = true;

    // System.NullReferenceException thrown here
    test.Update();
}

抛出的异常是:

System.NullReferenceException was unhandled
  Message="Object reference not set to an instance of an object."
  Source="SubSonic.Core"
  StackTrace:
       at SubSonic.Extensions.Database.ToUpdateQuery[T](T item, IDataProvider provider)
       at SubSonic.Repository.SubSonicRepository`1.Update(T item, IDataProvider provider)
       at HostMonitor.NewTestQueue.Update(IDataProvider provider) in E:\AppsDev.NET\_UK_Minds\Tollon Components\HostMonitor\Tollon.HostMonitor.TestGenerator\ActiveRecord\ActiveRecord.cs:line 593
       at HostMonitor.NewTestQueue.Update() in E:\AppsDev.NET\_UK_Minds\Tollon Components\HostMonitor\Tollon.HostMonitor.TestGenerator\ActiveRecord\ActiveRecord.cs:line 586
       at Tollon.HostMonitor.TestGenerator.Program.Main(String[] args) in E:\AppsDev.NET\_UK_Minds\Tollon Components\HostMonitor\Tollon.HostMonitor.TestGenerator\Program.cs:line 46
       at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 

为什么会这样?

更新:

我从 GitHub 获取了最新的源代码,但这会破坏 T4 模板生成的代码。生成的ActiveRecord.cs 不会编译并给出以下构建错误:

No overload for method 'Load' takes '1' arguments   
[Path snipped]\subsonic-SubSonic-3.0-4748517\SubSonic.Tests\BugReports\Generated\ActiveRecord.cs    
Line: 708

发生此错误的代码如下所示:

    public void Load(IDataReader rdr) {
        Load(rdr, true);
    }
    public void Load(IDataReader rdr, bool closeReader) {
        if (rdr.Read()) {

            try {
                rdr.Load(this); // <<-- Compile error happens here
                SetIsNew(false);
                SetIsLoaded(true);
            } catch {
                SetIsLoaded(false);
                throw;
            }
        }else{
            SetIsLoaded(false);
        }

        if (closeReader)
            rdr.Dispose();
    }

我确实尝试了原始 3.0.0.3 ActiveRecord 模板和来自 SubSonic.Tests 项目的 T4 模板。

【问题讨论】:

    标签: c# activerecord subsonic subsonic3


    【解决方案1】:

    我设法抽出一些时间来重新审视并解决这个问题。

    让我感到震惊的是,我错过了 rdr.Load() 方法是一个扩展方法(它 ~4am)并且它的方法签名更改为:

    public static void Load<T>(this IDataReader rdr, T item)
    

    到:

    public static void Load<T>(this IDataReader rdr, T item, List<string> ColumnNames)
    

    总之长话短说,一旦我意识到这一点并对该方法进行了查找用法,所有调用都只是通过null。然后我只是修改了ActiveRecord.tt T4 模板来反映这一点。

    【讨论】:

    • 只是为了澄清这里发生了什么。 SubSonic repo 的最后一次签入是修复 Linq 投影,它已经完成了,但它改变了扩展方法的方法签名,并且该更改需要向下游传播到 t4 模板。正如您在回答中所说,任何人都可以通过确保他们的模板传递一个默认值为 null 的额外参数来解决此问题,但它需要修复,所以我会尽快找到一些时间来帮助解决它。
    • @Adam - 我不介意在周末修复这个问题,另外我还得到了一些 Git 练习,如果能对项目做出一点小改动会很好。
    • 那太好了,去吧。
    猜你喜欢
    • 2010-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-28
    • 2013-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多