DBExtensions vom EdR - NullreferenceException

  • VB.NET

Es gibt 16 Antworten in diesem Thema. Der letzte Beitrag () ist von Marsianer.

    DBExtensions vom EdR - NullreferenceException

    Hi,
    habe die DBExtensions des Erfinder des Rades bei mir eingebunden und folgendes Problem beim saven des DataSets, wenn ich die Werte einer neuen Row aus unabhängigen Controls übers DataSet in die DB schreiben will:
    System.NullReferenceException wurde nicht behandelt.
    Message=Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt.
    Source=WinFormHelpers
    StackTrace:
    bei System.Windows.Forms.FormX.Save(DataSet dts, Form frm, Boolean checkForChanges) in D:\DBExtensions\AllTogether\Helpers\WinFormHelpers\FormX.vb:Zeile 70.
    bei MeinFinanzKnecht.frmBuchungNeu.btnOK_Click(Object sender, EventArgs e) in E:\Finanzen\MeinFinanzKnecht\MeinFinanzKnecht\Forms\frmBuchungNeu.vb:Zeile 97.
    bei System.Windows.Forms.Control.OnClick(EventArgs e)
    bei System.Windows.Forms.Button.OnClick(EventArgs e)
    bei System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
    bei System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
    bei System.Windows.Forms.Control.WndProc(Message& m)
    bei System.Windows.Forms.ButtonBase.WndProc(Message& m)
    bei System.Windows.Forms.Button.WndProc(Message& m)
    bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
    bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
    bei System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
    bei System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
    bei System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
    bei System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
    bei System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
    bei Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
    bei Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
    bei Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
    bei MeinFinanzKnecht.My.MyApplication.Main(String[] Args) in 17d14f5c-a337-4978-8281-53493378c1071.vb:Zeile 81.
    bei System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
    bei System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
    bei Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
    bei System.Threading.ThreadHelper.ThreadStart_Context(Object state)
    bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
    bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
    bei System.Threading.ThreadHelper.ThreadStart()
    InnerException:

    Der Fehler tritt in FormX.vb(Save-Extension) auf, der von folgendem Code aufgerufen wird:

    VB.NET-Quellcode

    1. Private Sub btnOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOK.Click
    2. Dim neuerDS As DataRow
    3. neuerDS = Me.DsFinanzKnecht.Buchung.NewRow
    4. neuerDS.Item("Name") = txtName.Text.ToString
    5. If optEinnahme.Checked = True Then
    6. neuerDS.Item("Buchungsart_id") = "Einnahme"
    7. Else
    8. neuerDS.Item("Buchungsart_id") = "Ausgabe"
    9. End If
    10. neuerDS.Item("Beginn") = Convert.ToDateTime(cmbBeginn.SelectedValue)
    11. neuerDS.Item("Ende") = Convert.ToDateTime(cmbEnde.SelectedValue)
    12. neuerDS.Item("Kategorie_id") = lstKategorie.SelectedValue
    13. neuerDS.Item("Konto_id") = lstKonto.SelectedValue
    14. neuerDS.Item("Zahlungsart_id") = lstZahlungsart.Text
    15. neuerDS.Item("Fälligkeit_id") = lstFälligkeit.Text
    16. neuerDS.Item("Betrag") = txtBetrag.Value
    17. neuerDS.Item("Bemerkungen") = txtBemerkungen.Text
    18. Me.DsFinanzKnecht.Buchung.Rows.Add(neuerDS)
    19. DsFinanzKnecht.Save(Me)
    20. End Sub


    Ich komm nicht drauf, was schief geht. Die Werte in der neuen Row werden m.E. korrekt übernommen. Habe das nachgeprüft, in dem ich über neuerDS.Item.Array iteriert bin und das alles in eine msgbox geschrieben habe. Hängt als Anlage dran. In der Save-Extension kommt auch das richtige DataSet an (jedenfalls hats den richtigen Namen) und CheckForChanges ist auf True.

    Bitte help!
    Bilder
    • FinanzknechtNeueBuchung.PNG

      68,22 kB, 1.333×666, 97 mal angesehen
    Ich code nur 'just for fun'! Damit kann ich jeden Mist entschuldigen, den mein Interpreter verdauen muss :D
    Also den Fehler seh ich jetzt auch nicht, aber warum tust du so umständlich neuerDS.Item("bla") = convert.Blub ?
    Versuch ma volgendes:

    VB.NET-Quellcode

    1. 'statt neuerDS = Me.DsFinanzKnecht.Buchung.NewRow
    2. neuerDS = Me.DsFinanzKnecht.Buchung.NewBuchungRow
    3. 'und denn mit Intellisense
    4. neuerDS.Beginn = Convert.ToDateTime(cmbBeginn.SelectedValue)

    Ich finde Zugriffe über Item("String") oder gar mit Indexnummern immer nich so schön. Vor allem hilft dir so die Intellisense bei der Tipperei.
    Wenn du dich übrigens für Datetimepicker entscheiden könntest, brauchst du nichtma Convert.ToDateTime. Da kannste glaub auch nen Benutzerformat für die Anzeige festlegen.

    Fiel Fergnügen

    Vatter
    :thumbsup: Seit 26.Mai 2012 Oppa! :thumbsup:

    ErfinderDesRades schrieb:

    bei NullRefException gehts doch immer drum, rauszukriegen, welches Objekt Nothing ist.

    Eben. Die Save-Extension verlangt, dass ihr eine Form übergeben wird. Tu ich auch (wird als Me übergeben und kommt laut Lokal-Fenster da auch an). Die Extension arbeitet mit zwei Objekten (DataSet und Form), die aber nach meiner Ansicht, bei nicht Nothing sind (s. Anhang). :wacko: :wacko: :wacko: Ich blick net durch.

    @Vatter: Danke für die Tipps
    Bilder
    • LokalFenster.PNG

      8 kB, 994×114, 96 mal angesehen
    Ich code nur 'just for fun'! Damit kann ich jeden Mist entschuldigen, den mein Interpreter verdauen muss :D

    VB.NET-Quellcode

    1. 68 <Extension()> _
    2. 69 Public Sub Save(ByVal dts As DataSet, ByVal frm As Form, Optional ByVal checkForChanges As Boolean = True)
    3. 70 dts.Attach.Save(frm, checkForChanges)
    4. 71 End Sub
    Ich code nur 'just for fun'! Damit kann ich jeden Mist entschuldigen, den mein Interpreter verdauen muss :D
    Ich hab den bösen Verdacht, dass es das DataSet ist... ich kapier aber nicht warum... lass mir mal Zeit drüber nachzudenken. Vll. sagste mir wenigstens, obbich auf der richtigen Spur bin.
    Ich code nur 'just for fun'! Damit kann ich jeden Mist entschuldigen, den mein Interpreter verdauen muss :D
    nö, bistenich.
    Dein bild zeigt doch, dass weder das Dataset noch das Form Nothing sind, und checkForChanges ist ein Boolean, also keine Klasse, und kann daher nicht nothing sein.
    Bleibt übrig?

    Ich denke daher, du hast das Dataset nicht registriert (also hofflich isses das).
    Tja,...

    in meiner BuchungNeu.vb steht fett über allem:

    VB.NET-Quellcode

    1. Imports MeinFinanzKnecht.dsFinanzKnecht


    Oder meintest du jetzt was anderes. Meinste dieses "Me.dsFinanzKnecht.register(Me)"? Das habbich nicht gemacht...sollich?
    Ich code nur 'just for fun'! Damit kann ich jeden Mist entschuldigen, den mein Interpreter verdauen muss :D
    Jo, mit einem unregistrierten Dataset worken die Extensions nicht.

    Vlt machichn Update, dass da eine speziellere Fehlermeldung ausgibt.

    Oder ich bau was ein, was auch nachträglich registriert.

    Nee - man muß registrieren, damit das Dataset auf das einzige gesetzt wird - ohne Registrierung wern ja auch gar keine Werte angezeigt, weil die ja in einem anneren Dataset liegen.

    Ist also eigenartig, dass erst beim Saven ein Fehlverhalten auftritt.

    Edit: Übrigens - hat Vatter schon angemerkt - dein Code aus post#1 hat erhebliches Optimierungspotential - den kann man eiglich nicht so lassen.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Na, die Werte wurden bisher angezeigt, weil ich meine TableAdapters noch drinne hatte :D

    Ja, ich weiß, mein Code ist verbesserungswürdig :whistling: , ich lern ja noch. Momentan würg ich mit der Registrierung des DataSets rum. Habe versucht, ne Codezeile aus deinem Tut zweckzuentfremden (die mitm FlowDesign: Register.Connection.Fill). Problem ist jetzt, dass in deinem Tut die Connection-Extension zwei Parameter übergeben bekommt (die eigentliche Connection und ne Anweisung, wie sie bei Konflikten reagieren soll). Mein VB sacht mir aber, dass die Connection-Extension gar keine Params haben darf :pinch: . Na, ich werd schon noch drauf kommen.
    Ich code nur 'just for fun'! Damit kann ich jeden Mist entschuldigen, den mein Interpreter verdauen muss :D
    naja - inzwischen habich die DBExtensions ja geupdated, und jetzt muß man das Dataset mit einer DBFactory initialisieren.
    Aber beim Registern (FlowDesign) kann man die einzelnen Elemente der Kette auch weglassen, oder jeweils in einer eigenen zeile schreiben. Also um ein 2. Dataset zu registrieren darf man ihm glaub nicht einen neuen DatasetAdapter zuweisen, sondern einfach:

    VB.NET-Quellcode

    1. FinanzKnechtDts.Register(Me)
    und feddich.

    Am besten das Northwind-Sample nochma angugge.
    In frmMain wird der DatasetAdapter gebastelt, zugewiesen unds Dataset registriert (im Flow), in frmRefillStore wird nur das dortige Dataset registriert (wodurch alles umgestöpselt wird auf das Dataset mit dem DatasetAdapter)

    also diese Kette im FlowDesign

    VB.NET-Quellcode

    1. Me.AlignOnTop.NorthWindDts.Adapter(adp).Register(Me)
    kann man auch konventionell formulieren

    VB.NET-Quellcode

    1. Me.AlignOnTop()
    2. Me.NorthWindDts.Adapter(adp)
    3. Me.NorthWindDts.Register(Me)
    Wobei .AlignOnTop ja nix mittm Dataset zu tun hat

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „ErfinderDesRades“ ()

    ErfinderDesRades schrieb:

    Dein Code aus post#1 ist eine untypisierte gräuseligkeit, die die typisierten Properties der BuchungRow komplett ignoriert - hastedas eiglich inzwischen überarbeitet?


    ... hier kömm ich an den Punkt, wo ich derzeit noch nicht mitkömm. Was sind typisierte Properties? ?(
    Jedenfalls bin ich mit den Extensions net so richtig klargekommen. Bei deinen Tuts war ja auch klar, dass man ein bestimmtes Wissen braucht (is jetzt kein Vorwurf oder so!). Irgendwo fehlten mir da die Kenntnisse, obwohls ja eigentlich einfacher anzuwenden wäre, wenn mans richtig implementiert. Bei meinem Level hab ich mehr oder minder deine Samples abgeschrieben und auf mich umzufummeln versucht, was ständig zu Fehlern führte. :whistling: Und da binnich nicht weitergekommen und habe erstmal wieder auf Tableadaptermanager und Konsorten zurückgeschraubt (war ja auch die Basis meiner Fragen in den letzten Threads). Das habe ich dann letztlich zum Funktionieren gekriegt. Jetzt heißt es erstmal, Finger weg vonner Datenbankanbindung (weil die funktioniert jetz auf konventionellem Wege) und das ExtensionMonster muss im Schrank auf seinen nächsten Einsatz warten.
    Ich code nur 'just for fun'! Damit kann ich jeden Mist entschuldigen, den mein Interpreter verdauen muss :D
    nee, hat mit DBExtensions nix zu tun - dieser Code hier:

    VB.NET-Quellcode

    1. Private Sub btnOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOK.Click
    2. Dim neuerDS As DataRow
    3. neuerDS = Me.DsFinanzKnecht.Buchung.NewRow
    4. neuerDS.Item("Name") = txtName.Text.ToString
    5. If optEinnahme.Checked = True Then
    6. neuerDS.Item("Buchungsart_id") = "Einnahme"
    7. Else
    8. neuerDS.Item("Buchungsart_id") = "Ausgabe"
    9. End If
    10. neuerDS.Item("Beginn") = Convert.ToDateTime(cmbBeginn.SelectedValue)
    11. neuerDS.Item("Ende") = Convert.ToDateTime(cmbEnde.SelectedValue)
    12. neuerDS.Item("Kategorie_id") = lstKategorie.SelectedValue
    13. neuerDS.Item("Konto_id") = lstKonto.SelectedValue
    14. neuerDS.Item("Zahlungsart_id") = lstZahlungsart.Text
    15. neuerDS.Item("Fälligkeit_id") = lstFälligkeit.Text
    16. neuerDS.Item("Betrag") = txtBetrag.Value
    17. neuerDS.Item("Bemerkungen") = txtBemerkungen.Text
    18. Me.DsFinanzKnecht.Buchung.Rows.Add(neuerDS)
    19. 'wiede und obde savest ist nicht Thema
    20. End Sub
    Das sind alles untypisierte Zugriffe, und die Items werden über StringSchlüssel addressiert, und sind vom Typ Object.

    Da fangichs weinen an, weil das geht auch ordentlich typisiert, sodaß du dich mit den Stringschlüsseln nicht verschreiben kannst, und auch keine falschen Datentypen reinpacken kannst:

    VB.NET-Quellcode

    1. Dim neuerDS As BuchungRow = Me.DsFinanzKnecht.Buchung.NewBuchungRow
    2. neuerDS.Name = txtName.Text
    3. If optEinnahme.Checked = True Then
    4. neuerDS.Buchungsart_id = "Einnahme"
    5. Else
    6. neuerDS.Buchungsart_id = "Ausgabe"
    7. End If
    8. neuerDS.Beginn = CType(cmbBeginn.SelectedValue, DateTime)
    9. neuerDS.Ende = CType(cmbEnde.SelectedValue, DateTime)
    10. neuerDS.Kategorie_id = CInt(lstKategorie.SelectedValue)
    11. neuerDS.Konto_id = CInt(lstKonto.SelectedValue)
    12. neuerDS.Zahlungsart_id = lstZahlungsart.Text
    13. neuerDS.Fälligkeit_id = lstFälligkeit.Text
    14. neuerDS.Betrag = Decimal.Parse(txtBetrag.Value)
    15. neuerDS.Bemerkungen = txtBemerkungen.Text
    16. Me.DsFinanzKnecht.Buchung.AddBuchungRow(neuerDS)

    Die ganzen Properties der BuchungRow habichmir nicht ausgedacht, sondern die sind so generiert, davon kannstedich im Objectbrowser überzeugen.

    Und dann ists immernoch gräuselig, denn mit Databinding könntestedir auch die ganzen Typumwandlungen ebenfalls sparen.

    vlt. doch nochmal mehr mit Databinding beschäftigen, und den 4 Views, und die Validiererei eher hintanstellen.
    Wie gesagt: die 4 Views haben nix mitte DBExtensions zu tun - Databinding ist Kernkompetenz von ADO.Net und WinForms.
    Ach sooo, jetzt kapier ich.

    Nee, das war ein Irrweg. Der Versuch überne ungebundene Form die Create-Schiene abzudecken.
    Ist eingestampft, weil ich letztlich auch nicht zum laufen gekriegt habe. Da haben mir selbst die Extensions nicht geholfen. Jetzt läufts wieder über Databinding (allerdings mit TableAdaptern und TableAdapterManager) und funktioniert. Ich hatte das übrigens so wie Vatter und du empfohlen habt, diese Item-Geschichte gekillt und das über NewRow versucht aber aus irgend einem Grund wollte er mir die Properties nicht an meinen NeuerDS ranhängen (wurden auch net in der IntelliSense angezeigt). Da habe ich garantiert wieder eine Einstellung oder irgenwas vergessen gehabt oder falsch gesetzt. Das war dann genau der Punkt, wo ich mit diesem Ungebunden-Kram aufgegeben und zum Databinding zurückgewechselt habe.
    Lag garantiert nicht an deinen Extensions ^^.

    Databinding ist Kernkompetenz von ADO.Net und WinForms.
    Jo und ich bin noch Zauberlehrling... die Geister, die ich rief... ;)
    Ich code nur 'just for fun'! Damit kann ich jeden Mist entschuldigen, den mein Interpreter verdauen muss :D