2010-01-26 4 views
2

J'ai une simple table avec une clé primaire (Identity) et quelques colonnes de type varchar. Je tente de supprimer/détruire un enregistrement avec clé primaire donnée en utilisant la syntaxe suivante:Subsonic 3 ActiveRecord Supprimer/détruire une exception étrange

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

mais quand on l'appelle, je reçois suivant Exception:

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

La trace de la pile est comme suit:

 
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: - J'ai une solution de contournement de t sa réponse, à savoir obtenir l'objet avec une clé donnée de db et ensuite appeler delete. Cela fonctionne mais je veux savoir pourquoi je reçois cette exception. Aussi j'utilise SS 3.0.3 (téléchargé aujourd'hui (26Jan2K10)).

Répondre

1

Cela ressemble à un bogue, car le dépôt SubSonicRepository dont dépend la méthode ActiveRecord Destroy n'a pas de surcharge Delete(expression).

Je pense que si vous allez dans votre fichier modèle ActiveRecord.tt et trouvez:

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

et remplacer Delete avec DeleteMany qui supprimera tous les enregistrements retour vrai pour l'expression donnée (espérons que celui si vous utilisez la clé primaire :)

GC

+0

semble prometteur. Je vais l'essayer. – TheVillageIdiot

+0

J'ai enregistré un problème dans le projet Templates sur GitHub. –

1

Je ne suis pas familier avec la bibliothèque ou la fonction, mais le message d'erreur implique que vous passez une fonction en tant que paramètre où un Int32 est attendu. Et en fait, vous passez une fonction lambda (le "=>") comme paramètre à détruire. Donc, la première chose à vérifier est de savoir si Destroy veut vraiment une fonction, ou un Integer.

Si ce n'est pas le cas, notez que la fonction lambda renvoie un bool (le résultat d'une comparaison ==), mais l'erreur implique qu'un Int32 est désiré. Vous pourriez avoir à convertir votre bool int, que vous pouvez facilement faire avec l'opérateur?: Comme ceci:

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

Mais bien sûr, les deux réponses dépendent de ce que le paramètre Destroy est en fait attendre.