Subsonic 3 ActiveRecord Удалить / уничтожить выбрасывание странного исключения - PullRequest
2 голосов
/ 26 января 2010

У меня есть простая таблица с первичным ключом (Identity) и несколькими столбцами типа varchar. Я пытаюсь удалить / уничтожить запись с заданным первичным ключом, используя следующий синтаксис:

SS3Test.DAL.TestClass.Destroy(x => x.TestId == _testId);

но когда он вызывается, я получаю следующее исключение:

Failed to convert parameter value from a Func `2 to a Int32.

Трассировка стека выглядит следующим образом:

System.InvalidOperationException was unhandled
  Message="Failed to convert parameter value from a Func`2 to a Int32."
  Source="SubSonic.Core"
  StackTrace:
       at SubSonic.Query.SqlQuery.Execute()
       at SubSonic.Repository.SubSonicRepository`1.Delete(Object key, IDataProvider provider)
       at SubSonic.Repository.SubSonicRepository`1.Delete(Object key)
       at SS3Test.DAL.TestClass.Destroy(Func`2 expression) in E:\temp\SS3TEst\SS3Test.DAL\ActiveRecord.cs:line 2149
       at SS3Test.Model.TestClass.Delete(Int32 warrantyId, Boolean destroy) in E:\temp\SS3TEst\SS3Test.Model\TestClass.cs:line 84
       at SS3Test.GUI.FrmTestClass.btnDelete_Click(Object sender, EventArgs e) in E:\temp\SS3TEst\SS3Test.GUI\FrmTestClass.cs:line 72
       at System.Windows.Forms.Control.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
       at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
       at System.Windows.Forms.Control.WndProc(Message& m)
       at System.Windows.Forms.ButtonBase.WndProc(Message& m)
       at System.Windows.Forms.Button.WndProc(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
       at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.Run(Form mainForm)
       at SS3Test.GUI.Program.Main() in E:\temp\SS3TEst\SS3Test.GUI\Program.cs:line 21
       at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: System.InvalidCastException
       Message="Failed to convert parameter value from a Func`2 to a Int32."
       Source="System.Data"
       StackTrace:
            at System.Data.SqlClient.SqlParameter.CoerceValue(Object value, MetaType destinationType)
            at System.Data.SqlClient.SqlParameter.GetCoercedValue()
            at System.Data.SqlClient.SqlParameter.Validate(Int32 index, Boolean isCommandProc)
            at System.Data.SqlClient.SqlCommand.BuildParamList(TdsParser parser, SqlParameterCollection parameters)
            at System.Data.SqlClient.SqlCommand.BuildExecuteSql(CommandBehavior behavior, String commandText, SqlParameterCollection parameters, _SqlRPC& rpc)
            at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
            at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
            at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe)
            at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
            at SubSonic.DataProviders.DbDataProvider.ExecuteQuery(QueryCommand qry)
            at SubSonic.Query.SqlQuery.Execute()
       InnerException: System.InvalidCastException
            Message="Object must implement IConvertible."
            Source="mscorlib"
            StackTrace:
                 at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)
                 at System.Data.SqlClient.SqlParameter.CoerceValue(Object value, MetaType destinationType)

PS: - У меня есть обходной путь из этого ответа, а именно, чтобы получить объект с данным ключом из db и затем вызвать delete для него. Это работает, но я хочу знать, почему я получаю это исключение. Также я использую SS 3.0.3 (скачано сегодня (26Jan2K10)).

Ответы [ 2 ]

1 голос
/ 02 февраля 2010

это выглядит как правильная ошибка, так как SubSonicRepository, от которого зависит метод ActiveRecord Destroy, не имеет перегрузки Delete(expression).

Я думаю, что если вы зайдете в файл шаблона ActiveRecord.tt и найдете:

    public static void Destroy(Func<<#=tbl.ClassName#>, bool> expression) {
        var repo = GetRepo();
        repo.Delete(expression);
    }

и замените Delete на DeleteMany, который удалит все записи, возвращающие значение true для данного выражения (возможно, только ту, если вы используете первичный ключ:)

GC

1 голос
/ 28 января 2010

Я не знаком с библиотекой или функцией, но сообщение об ошибке подразумевает, что вы передаете функцию в качестве параметра, где ожидается Int32. И на самом деле вы передаете лямбда-функцию ("=>") в качестве параметра для Destroy. Поэтому первое, что нужно проверить - действительно ли Destroy хочет функцию или целое число.

Если это не так, обратите внимание, что лямбда-функция перестраивает bool (результат сравнения ==), но ошибка подразумевает, что требуется Int32. Возможно, вам придется преобразовать bool в int, что вы можете легко сделать с помощью оператора?: Например:

x => ((x.TestId == _testId) ? 1 : 0)

Но, конечно, оба ответа зависят от того, что на самом деле ожидает параметр Destroy.

...