Laden...

Forenbeiträge von Alesia Ingesamt 15 Beiträge

27.01.2023 - 13:04 Uhr

Ja da hattest du recht.
Ich bin das nochmal durchgegangen und hab das alles behoben.
Läuft nun nach dem 3-Schichten-Prinzip wie du vorgeschlagen hast.
Bringt schon Vorteile mit sich, das stimmt.

24.01.2023 - 18:19 Uhr

Vielen Dank,
das war auch die Lösung.
Ich hatte den Repository Service nicht registriert, auch nicht wirklich realisiert das die "App" den Service kennen muss, da die App keine Projektreferenz zu der Datenschicht hat.
Dachte das schlingt sich von Schicht zu Schicht, sodass nur die darüberliegende vom drunterliegenden Service wissen muss.
Die richtige Reihenfolge der Registrierung ist auch wichtig, das war mein nächster Fehler.

23.01.2023 - 23:09 Uhr

Kann das sein, dass man seine Beiträge nicht bearbeiten kann?

Ich werde einfach nicht fündig zu dem Problem, sorry für den vielen Code, aber ich verstehs an dem Punkt nicht weshalb das passiert.

Drei Klassenbibliotheken und ein Server Projekt
Data
Service
Model
Blazor Server = App

Referenz in Data = Service / Model
Referenz in Service = Data / Model
Referenz in App = Service

In Data ist der DBContext, ganz normal wie er sein sollte.


    public class DataContext : DbContext
    {
        public DataContext(DbContextOptions<DataContext> options) : base(options)
        {
        }
        public DbSet<Adresse> Adresse { get; set; }
    }
}

In Data wird mein Repository abgerufen


        private readonly DataContext _context;

        public AdresseRepository(DataContext context)
        {
            _context = context;
        }
        public async Task<List<Adresse>> GetAdressen()
        {

            var adressenTable = await _context.Adresse
                            .ToListAsync();
            return adressenTable;
        }

Im Service ist eine Klasse die das Repository in Data abruft


	public class AdresseService : IAdresseService
    {
        private IAdresseRepository _adresseRepository;

        public AdresseService(IAdresseRepository adresseRepository)
        {
            _adresseRepository = adresseRepository;
        }

        public async Task<List<Adresse>> GetAdressen()
        {
            List<Adresse> adressenTable = new List<Adresse>();
            adressenTable = await _adresseRepository.GetAdressen();
            return adressenTable;
        }
    }

In der Index.razor per @inject IAdresseService adresseService, rufe ich var adressenTable = await adresseService.GetAdressen(); auf

In der Program.cs ist der Context und der Service registriert


builder.Services.AddDbContext<DataContext>
                (options => options.UseSqlServer("String"));

builder.Services.AddScoped<IAdresseService, AdresseService>();

Beim starten der App bekomme ich "Some services are not able to be constructed (NET.Service.IAdresseService) bezogen auf NET.Data.IAdressRepository
> Beim ganzen lesen auf google würde ich sagen, dass irgendwo die Referenz zur Klassenbibliothek fehlt.
> Hab was von DBContext Factory gelesen und so, aber irgendwie komm ich nicht weiter.

Gibt es bereits einen Artikel der mein Problem behandelt und ggf. lösen kann, oder habt ihr eine Idee dazu, wo ich was vergessen habe?

23.01.2023 - 20:54 Uhr

Alles klar verstanden, soweit dachte ich es mir schon.
Hab gerade meine Test App parallel dazu mal in das neue System gebracht.
Aktuell hänge ich noch daran, dass in der programm.cs ein Fehler kommt, den ich gerade er-google.

"Some services are not able to be constructed"


using test.Service;

builder.Services.AddScoped<IAdresseService, AdresseService>();

23.01.2023 - 19:48 Uhr

Bin dir ja dankbar das du antwortest, dann musst du nicht noch ein Video anschauen 😉
Aber die Grundstruktur entspricht dem was du verlinkt hast.

Grundsätzlich habe ich die Struktur so auch verstanden, wo es gedanklich aber noch hängt ist bei der Übergabe der Daten in den Service.

Das Datenbank ist unterteilt in 4 Tabellen, die für den Abruf einer "Anschrift" in meinem Fall benötigt werden.
Ich würde jetzt als nächstes 3 weitere Datenmodell Klassen bilden, die meine anderen benötigten Tabellen abruft.

Im Service ruft ich also meine Daten von jedem Datenmodell ab.
Mache ich dann im Service schon das ViewModel oder Injecte ich den Service in meine blazor Komponente und mach da erst ein ViewModel draus?

23.01.2023 - 18:35 Uhr

Sind auch meine ersten Versuche in dem Umfeld, man liest eben sehr viel unterschiedliches.
Use-Cases, Pluginmethode, Drei-Schichten-Architektur.

Ich kann das noch nicht ganz so verstehen mit deinem Ansatz, ist das so in etwa der Weg?

Müsste meine Datenzugriffsschicht den anonymen select als return liefern, die Logikschicht müsste ein Viewmodel draus machen und die Präsentationsschicht ruft das fertige Model ab, zeigt an und gibt Änderungen wieder an die Logikschicht, die wiederum aus dem ViewModel ein DB Model macht, das dann in der Datenzugriffsschicht verarbeitet wird?

Ich hab ein relativ altes Video gefunden, dass erstmal logisch klingt.
Ist das so zu empfehlen?
3 Schichten Architektur

22.01.2023 - 13:43 Uhr

Danke für die Antworten.
Die Microsoft Hilfe beschreibt keine Where Clausel innerhalb des Joins.
Ebenso arbeite ich in einer Apple Umgebung und kann den Converter nicht nutzen.

Jedoch habe ich wie es so oft der Fall ist, nochmal drüber nachgedacht.
Der Fehler lag nie an meinem LINQ Tests, sondern an dem Model das ich nicht gegen NULL geprüft habe.

Der vollständige LINQ zu meiner Antwort ist:


                from adr in adressen
                join ans in anschriften on adr.AdrNr equals ans.AdrNr
                from asp in ansprechpartner.Where(a => ans.AnsNr == a.AnsNr && a.StdKz == true).DefaultIfEmpty()

Das ausschlaggebende ist jedoch gewesen:


                    StdAnsprechpartner = asp == null ? "" : asp.VNa + " " + asp.NNa,


Somit wäre das Problem gelöst 😉

22.01.2023 - 00:37 Uhr

Verwendetes Datenbanksystem: <SQL>

Hallo zusammen,

ich versuche irgendwie verzweifelt ein SQL Statement in LINQ abzubilden.
Zur Verfügung habe ich 3 einzelne Datenbanktabellen, dessen Keys jeweils Adressen (adrnr), Anschriften (adrnr, ansnr) und Ansprechpartner (adrnr, ansnr, aspnr) sind.
Was ich aktuell habe, bringt nicht das Ergebnis was ich versuche abzubilden.

Ich suche im konkreten von hinten nach vorne

Den Standart Ansprechpartner (der jeweiligen Anschrift), der Anschrift(en), der Adresse. 1:n:n
Eine Adresse hat IMMER mind. 1 Anschrift und kann mehrere haben, aber nicht jede Anschrift hat zwingend einen Ansprechpartner (wovon eine Anschrift aber mehrere haben kann), wenn dann muss der Ansprechpartner mit dem StdKz == true abgerufen werden

Anhand folgendes Beispiels hatte ich mich schon versucht, jedoch kriege ich damit nur Adressen zurück die einen Ansprechpartner haben.
Wenn kein Ansprechpartner vorhanden ist, kriege ich auch die jeweilige Adresse nicht.

https://www.codeproject.com/Questions/5301181/How-to-use-linq-to-join-3-tables-in-Csharp

Hat jemand einen entscheidenen Tipp für mich?

Mein aktueller Code:


            var adressen = await _context.Adressen
                        .Include(b => b.Bild)
                        .Include(s => s.Status)
                        .ToListAsync();
            var anschriften = await _context.Anschriften
                        .ToListAsync();
            var ansprechpartner = await _context.Ansprechpartner
                        .Include(b => b.Bild)
                        .ToListAsync();

            var adressenListe =
            (
                from adr in adressen
// Inner Join da immer eine Anschrift existiert, bezogen auf die Adressnummer
                join ans in anschriften on adr.AdrNr equals ans.AdrNr
// Müsste ein LEFT Join sein, der als where ans.AdrNr == asp.AdrNr && ans.AnsNr == asp.AnsNr && asp.StdKz == true beinhaltet
                join asp in ansprechpartner on ans.AnsNr equals asp.AnsNr


                select new AdressenViewModel()
                {
                    ID = ans.ID,
                    ERPID = ans.ID,
                    AdrNr = ans.AdrNr,
                    AnsNr = ans.AnsNr,
                    SuchBeg = adr.SuchBeg,
                    Branche = adr.Branche,
                    VtrNr = adr.VtrNr,
                    Na1 = ans.Na1,
                    Na2 = ans.Na2,
                    Na3 = ans.Na3,
                    Str = ans.Str,
                    PLZ = ans.PLZ,
                    Ort = ans.Ort,
                    LandBez = ans.LandBez,
                    Tel = ans.Tel,
                    EMail1 = ans.EMail1,
                    WSeite = ans.WSeite,
                    StdReKz = ans.StdReKz,
                    StdLiKz = ans.StdLiKz,
                    StdAnsprechpartner = asp.VNa + " " + asp.NNa,
                    Info = ans.Info,
                    Bild = adr.Bild,
                    GspKz = ans.GspKz,
                    ErstBzr = ans.ErstBzr,
                    AendBzr = ans.AendBzr,
                    ErstDat = ans.ErstDat,
                    LtzAend = ans.LtzAend
                });


24.12.2022 - 13:33 Uhr

Hallo zusammen,

Danke für die Antworten erstmal.

Was Papst schreibt, ist so nicht Abbildbar, da die Klasse im Web auf Modal basiert und auf Native mit DisplayAlert greift.
Jedoch habe ich nen weg über den Javascript Inject mit Alert() gefunden das zu lösen.
War jedoch auch nicht die beste Entscheidung das so zu splitten.

Ich hab gestern mal ein umfangreiches Tutorial noch angeschaut, was meine Grundlagen von Blazor in ein deutlich anderes Licht gerückt hat.
Wen es interessiert: CodingDroplet auf Youtube, der hat da was für C# and Blazor.
Er deckt so in der Basis alles ab, was ich mich grundsätzlich gefragt und die letzten paar Tage mit rumgeärgert habe.
Natürlich war dabei auch der Lernfaktor deutlich höher als bei Onkel google den ganzen Tag alte Beiträge zu lesen, wo jeder anders an die Sache rangeht.

Bin gerade dabei meine WinForms App eben umzuschreiben, hab aber erst angefangen.
Ich werde auf Basis des Tutorials nochmal neu aufbauen und schauen wie weit mich da der Weg trägt 🙂

23.12.2022 - 20:09 Uhr

Hallo zusammen,

gibt es einen Weg bei einem Hybrid Projekt, dass auf Shared Ressourcen zugreift, einen @inject Service Plattformabhängig zu definieren?

Ich habe einen DialogService der nur auf mobilen Geräten verfügbar ist und dort die nativen MAUI Funktionen nutzt.
Starte ich das Projekt jetzt im Browser, funktioniert natürlich die Seite mit dem jeweiligen Service @inject nicht mehr, da dies nicht in der Program.cs referenziert werden kann.

Ein Javascript Inject habe ich bereits, der abfängt ob ich mich auf Mobil oder Desktop bewege.
Ein "einfach Gedachter" Ansatz war das ganze im @Code Block abzufangen innerhalb der benötigten Funktion.
Da ich jedoch relativ neu mit Blazor arbeite, verstehe ich noch nicht so eine Menge davon.


    async void findAnschrift()
    {
        if (ansSuchBeg is not null)
        {
            var result = anschriftService.GetAnschriften(ansSuchBeg);
            anschriften = result;
        }
        else
        {
            if (isDevice == "mobile")
            {
                await DialogService.DisplayAlert("Kein Suchbegriff", "Bitte einen Suchbegriff eingeben", "OK");
            }
        }
    }

Geht leider nicht.
Der zweite Ansatz war die OnInitialized


    protected async override void OnInitialized()
    {
        base.OnInitialized();
        mobile = await jsRuntime.InvokeAsync<bool>("isDevice");
        isDevice = mobile ? "Mobile" : "Desktop";
        if (isDevice == "mobile")
        {
            @inject IDialogService DialogService
        }
    }

Leider geht das auch nicht.
Scheint mir so als ob es egal ist wo das @inject steht, es wird sofort beim laden der Seite bearbeitet ohne Code zu beachten.
Hab irgendwie dazu auch nichts bei Onkle Google gefunden.

21.12.2022 - 14:54 Uhr

Die Prüfung runter bis auf den foreach Schleife, habe ich nun soweit implementiert, dank deiner Hilfestellung.
Innerhalb der Schleife muss wie du schon bestätigt hast, die Prüfung der Node und die Prüfung des Inhaltes stattfinden.


                    XmlNode? nodeCheck = node1.SelectSingleNode("Na1");
                    if (nodeCheck is not null)
                    {
                        Na1 = nodeCheck.InnerText;
                    }

                    nodeCheck = node1.SelectSingleNode("Na2");
                    if (nodeCheck is not null)
                    {
                        Na2 = nodeCheck.InnerText;
                    }

Ist das der richtige Weg aus deiner Sicht?

21.12.2022 - 14:02 Uhr

Hallo Abt,

verstanden, irgendwie habe ich im ersten durchlesen deinen Link nicht bemerkt.
Tatsächlich beschreibst du da ja auch die Vorgehensweise die passt.
Habe es kurz nach meinem Post dann auch herausgefunden.

Wenn ich deinen Post richtig verstanden habe, prüfst du, speicherst zwischen und verwendest die geprüfte Variable, macht auch Sinn.
Wie läuft das dann in einer Schleife in der die Node in meinem Beispiel erst generiert wird?


            if(idNodes is not null)
            {
                foreach (XmlNode node1 in idNodes)
                {}
}

Die idNodes werden geprüft und als geprüft erkannt, aber die node1 die erzeugt wird, kann ja potenziell InnerTexte enthalten die Null sind.
Ebenso kann es sein, dass der Node nicht vorhanden ist.
Eine Prüfung auf das vorhanden sein von der jeweiligen Node, funktioniert schon nicht, zumindest so wie ich es nun versucht habe.


XmlElement el = (XmlElement)XmlResponse.SelectSingleNode("Na2");
if (el != null)

21.12.2022 - 13:36 Uhr

Hallo Abt,

danke für die Ausführliche Info zu dem ganzen.
Man merkt ich befinde mich in der Lernphase des ganzen und bin nicht so bewandert mit Null Prüfungen.

Ein einfacher Gedanke von mir war nun, okay mach ich das halt.
Gepackt in eine If geprüft auf is not null oder != null geht.
Aber bei den SingleNodes und einer NodeList geht es nicht, zumindest nicht so.

Ich hatte ja im Vorfeld bereits viel Zeit investiert das Problem zu finden bzw. zu er-googlen.
In den meisten Beispielen wird eben kein Null geprüft oder es kommen um es mit deinen Worten zu fassen unsinniger Code dabei rum (? oder string.emtpy z.B.)


            if(XmlRequest.DocumentElement is not null)
            { 

Ich würde gerne daraus lernen und es auch dann richtig machen.
Gibt es von dir / jemanden ein Beispiel wie ich ein eine XmlNodeList und ein SelectSingleNote auf Null prüfe?

21.12.2022 - 12:23 Uhr

Hallo Th69,

Erstmal danke ich dir für den Tipp.
ich werd verrückt.
Suche da ewig nach einer Antwort und Lösungen und Sie kann so einfach sein.
Im Model und im Service habe ich #nullable disable ergänzt und siehe da es funktioniert.

Gibt es generell auch eine Lösung ohne diesen Parameter, ist der Code dann so "konform" oder würde ein anderer Entwickler hier den Kopf schütteln wenn ich überall das nullable deaktiviere.
Ich würde gerne daraus lernen und es optimieren für die Zukunft.

21.12.2022 - 10:32 Uhr

Hallo zusammen,
ich bin auf euch gestoßen und sehe eine hohe Aktivität in eurer Community und hoffe natürlich auch etwas beisteuern zu können.
Seit längerem programmiere ich Anbindungen an ein ERP-System und kam bisher immer alleine gut klar.
Eine App auf Basis von WinForms existiert bereits und diese bin ich gerade dabei umzuschreiben.
Meine Zielplattform ist .MAUI und Blazor.

Zum starten habe ich eine einfache .MAUI App generiert um zu sehen ob mein Connector und meine Models funktionieren, dies ist der Fall und macht keine Probleme.
Da ich die App jedoch auch in einer Webanwendung bereit stellen möchte, ist der nächste Weg also .MAUI mit Blazor.

Viel Text von mir, nun mein Problem.

"Dereferenzierung eines möglichen Null-Wertes" innerhalb meiner Blazor Umgebung.

Die Basis ist ein Model und ein Service, in meinem Fall "AnschriftService".
Ich schicke XML Daten an einen Connector, der dies auf der Seite meines ERP Systems dann verarbeitet.

Wie man im Code sieht, schließe ich für den ConnectorClient mit "?" bereits die null Prüfung aus.
Jetzt hänge ich aber am XML Element das NULL enthalten darf und auch ggf. zurückgibt.
Jedoch kriege ich hier den passenden Syntax nicht raus.


public class MAnschrift
{
    public string Na1 { get; set; }
    public string Na2 { get; set; }
}


        // Es müssen noch Textfelder übergeben werden in die Funktion
        public List<MAnschrift> GetAnschriften()
        {

            // XmlDocument für Parameter erstellen
            XmlDocument XmlRequest = new XmlDocument();
            XmlRequest.LoadXml("<Root/>");
            // AdrNr
            var node = XmlRequest.CreateElement("AdrNr");
            node.InnerText = "";
            XmlRequest.DocumentElement.AppendChild(node);

            // Connector initialisieren, Standard NULL
            ConnectorClient? client = null;
            client = new ConnectorClient();


            // Xml Übergabe ausführen
            XmlElement XmlResponse = client.ExecuteComplete(GlobalConnectorConfig.serverURL, GlobalConnectorConfig.connectorScriptFileName, GlobalConnectorConfig.connectorScript, XmlRequest.DocumentElement, 30);

            /*
            XmlElement el = (XmlElement)response.SelectSingleNode("Error");
            if (el != null)
                el.ParentNode.RemoveChild(el);
            */

            XmlNodeList idNodes = XmlResponse.SelectNodes("Anschrift");
            List<MAnschrift> anschriftListe = new List<MAnschrift>();

            foreach (XmlNode node1 in idNodes)
            {
                anschriftListe.Add(new MAnschrift()
                {
                    Na1 = node1.SelectSingleNode("Na1").InnerText,
                    Na2 = node1.SelectSingleNode("Na2").InnerText,
                });
            }
            return anschriftListe;
        }

Sowohl XmlRequest.DocumentElement.AppendChild(node); wird hier mit "Dereferenzierung eines möglichen Null Verweises" deklariert als auch viele andere Elemente dieses Codes.
Ebenso wird Na1 und Na2 im Model (eigene C# Klasse) angemerkt.
Könnte ich im Model mit "string?" umgehen, im XMLElement aber nicht.

Frage 1)
Kann mir jemand verständlich machen wieso die Blazor Umgebung die null-Werte anmeckert die .MAUI Umgebung jedoch nicht?

Frage 2)
Hat jemand möglichen Lösungsansatz gegen dieses Problem?