Files
2026-05-19 11:27:12 +02:00

14 KiB

Przykłady kodu - Podstawowe klasy ORM

Praktyczne przykłady użycia podstawowych klas logiki biznesowej enova365/Soneta.

Spis treści

Ważne zasady

Ten plik zakłada znajomość fundamentów — przed sięgnięciem po przykłady upewnij się, że są jasne:

  • Thread-safety (Session/Row/Table/Module/Context są single-threaded; BusApplication/Database/Login można współdzielić) — patrz session-login.md.
  • Transakcje biznesowe — każda zmiana obiektu (dodanie, modyfikacja property, kasowanie) wymaga otwartej transakcji session.Logout(editMode: true) zakończonej Commit(); zapis do bazy przez session.Save() poza transakcją. Szczegóły, w tym typy sesji, CommitUI() i optimistic locking — patrz session-login.md.
  • Bezpieczny kod — przy nowym kodzie i review weryfikuj reguły z safe-code.md.

Extension methods dla modułów

Dostęp do modułów przez extension methods:

var tm = session.GetTowary();
var hm = session.GetHandel();
var crm = session.GetCRM();
var kadry = session.GetKadry();
var bm = session.GetBusiness();

Dostęp do danych

Odczyt listy towarów

using Soneta.Business;
using Soneta.Towary;

public void WyswietlTowary(Login login)
{
    // Sesja tylko do odczytu
    using (var session = login.CreateSession(true, false, "OdczytTowarow"))
    {
        var tm = session.GetTowary();  // Extension method
        
        // Iteracja po kluczu podstawowym (WgKodu)
        foreach (Towar t in tm.Towary.WgKodu)
        {
            Console.WriteLine($"{t.Kod}: {t.Nazwa}");
        }
    }
}

Wyszukiwanie po kluczu

public Towar ZnajdzTowar(Session session, string kod)
{
    var tm = session.GetTowary();
    
    // Wyszukiwanie po kluczu unikalnym
    return tm.Towary.WgKodu[kod];
}

Iteracja z filtrowaniem

public void WyswietlAktywneTowary(Session session)
{
    var tm = session.GetTowary();
    
    foreach (Towar t in tm.Towary.WgKodu)
    {
        // Filtrowanie w kodzie
        if (t.Typ == TypTowaru.Towar)
        {
            Console.WriteLine(t.Nazwa);
        }
    }
}

Tworzenie obiektów

Dodawanie nowego towaru

public void DodajTowar(Login login)
{
    // Sesja edycyjna
    using (var session = login.CreateSession(false, false, "DodawanieTowaru"))
    {
        var tm = session.GetTowary();
        
        // Transakcja biznesowa - wymagana!
        using (var transaction = session.Logout(editMode: true))
        {
            // Utworzenie nowego obiektu
            var towar = new Towar();
            
            // Dodanie do tabeli (zmiana stanu na Added)
            tm.Towary.AddRow(towar);
            
            // Ustawienie właściwości
            towar.Kod = "NOWY001";
            towar.Nazwa = "Nowy towar";
            towar.Typ = TypTowaru.Towar;
            
            transaction.Commit();
        }
        
        // Zapisanie do bazy
        session.Save();
    }
}

Dodawanie dokumentu z pozycjami

public void UtworzFakture(Login login, Kontrahent kontrahentZInnejSesji, 
                          List<(Towar towar, int ilosc)> pozycjeZInnejSesji)
{
    using (var session = login.CreateSession(false, false, "TworzenieFaktury"))
    {
        var hm = session.GetHandel();
        
        // WAŻNE: Obiekty z innej sesji trzeba doczytać w bieżącej sesji!
        var kontrahent = session.Get(kontrahentZInnejSesji);
        
        // Cała operacja w jednej transakcji
        using (var transaction = session.Logout(editMode: true))
        {
            // Utworzenie nagłówka dokumentu
            var faktura = new DokumentHandlowy();
            hm.DokHandlowe.AddRow(faktura);
            
            faktura.Definicja = hm.DefDokHandlowe.WgSymbolu["FV"];
            faktura.Kontrahent = kontrahent;
            faktura.Data = Date.Today;
            
            // Dodanie pozycji
            int lp = 1;
            foreach (var (towarZInnejSesji, ilosc) in pozycjeZInnejSesji)
            {
                // Doczytaj towar w bieżącej sesji
                var towar = session.Get(towarZInnejSesji);
                
                var poz = new PozycjaDokHandlowego(faktura);
                faktura.Pozycje.AddRow(poz);
                
                poz.Towar = towar;
                poz.Ilosc = new Quantity(ilosc, towar.Jednostka.Kod);
                poz.Lp = lp++;
            }
            
            transaction.Commit();
        }
        
        session.Save();
    }
}

WAŻNE: W jednej sesji nie można mieszać obiektów z różnych sesji. Użyj session.Get(obiekt) aby doczytać obiekt w bieżącej sesji.

Modyfikacja obiektów

Aktualizacja pojedynczego obiektu

public void ZmienNazweTowaru(Login login, string kod, string nowaNazwa)
{
    using (var session = login.CreateSession(false, false, "EdycjaTowaru"))
    {
        var tm = session.GetTowary();
        var towar = tm.Towary.WgKodu[kod];
        
        if (towar != null)
        {
            using (var transaction = session.Logout(editMode: true))
            {
                towar.Nazwa = nowaNazwa;
                transaction.Commit();
            }
            session.Save();
        }
    }
}

Aktualizacja z transakcją biznesową

public void AktualizujCeny(Login login, string nazwaCeny, decimal procentPodwyzki)
{
    using (var session = login.CreateSession(false, false, "AktualizacjaCen"))
    {
        var tm = session.GetTowary();

        // Jedna transakcja dla całej pętli - szybciej i atomowo
        using (var transaction = session.Logout(editMode: true))
        {
            foreach (Towar t in tm.Towary.WgKodu)
            {
                var cena = t.Ceny[nazwaCeny];
                if (cena != null)
                {
                    cena.Netto = new DoubleCy(cena.Netto.Value * (1 + procentPodwyzki / 100));
                }
            }
            transaction.Commit();
        }

        session.Save();  // Zapisuje wszystkie zmiany do bazy
    }
}

Usuwanie obiektów

Usuwanie obiektu

public void UsunTowar(Login login, string kod)
{
    using (var session = login.CreateSession(false, false, "UsuwanieTowaru"))
    {
        var tm = session.GetTowary();
        var towar = tm.Towary.WgKodu[kod];
        
        if (towar != null)
        {
            using (var transaction = session.Logout(editMode: true))
            {
                towar.Delete();  // Zmiana stanu na Deleted
                transaction.Commit();
            }
            session.Save();  // Fizyczne usunięcie z bazy
        }
    }
}

Praca z kontekstem

Przykłady klasy parametrów dziedziczącej z ContextBase - patrz contextbase.md. Współdzielenie wartości przez Context - patrz context.md. Przykłady Workera z [Context] i akcji w menu Czynności - patrz worker-extender.md.

Praca z GuidedRow

Przykłady dostępu do historii zmian (ChangeInfos) i pracy z załącznikami (dodawanie z transakcją, odczyt, DefaultImage) - patrz datapack-guidedrow.md.

Dane konfiguracyjne vs operacyjne

Odczyt danych konfiguracyjnych

// Odczyt pojedynczej wartości
var opisDlaSzt = login.ExecuteConfig(configSession =>
    configSession.GetTowary().Jednostki.WgKodu["szt"]?.Opis);

// Odczyt listy wartości prostych
public string[] PobierzKodyJednostek(Login login)
{
    return login.ExecuteConfig(configSession => 
    {
        var tm = configSession.GetTowary();
        return tm.Jednostki.WgKodu.Select(j => j.Kod).ToArray();
    });
}

WAŻNE: Używając ExecuteConfig() nie można zwracać obiektów sesyjnych z sesji konfiguracyjnej, ponieważ może być używana w innym wątku do innych celów. Zwracaj tylko wartości proste lub kopie danych.

public void OdczytKonfiguracji(Login login)
{
    // Własna sesja konfiguracyjna - gdy potrzebny dostęp do obiektów
    using (var session = login.CreateSession(true, true, "Konfiguracja"))
    {
        var tm = session.GetTowary();
        
        foreach (Jednostka j in tm.Jednostki.WgKodu)
        {
            Console.WriteLine($"{j.Kod}: {j.Opis}");
        }
    }
}

Modyfikacja danych konfiguracyjnych

public void DodajJednostke(Login login, string kod, string opis)
{
    // Sesja edycyjna konfiguracyjna
    using (var session = login.CreateSession(false, true, "DodawanieJednostki"))
    {
        var tm = session.GetTowary();
        
        using (var transaction = session.Logout(editMode: true))
        {
            var jednostka = new Jednostka();
            tm.Jednostki.AddRow(jednostka);
            
            jednostka.Kod = kod;
            jednostka.Opis = opis;
            
            transaction.Commit();
        }
        
        session.Save();
    }
}

Pełny przykład - import towarów

public class ImportTowarow
{
    public void Importuj(Login login, string sciezkaPliku)
    {
        var dane = WczytajZPliku(sciezkaPliku);
        
        using (var session = login.CreateSession(false, false, "ImportTowarow"))
        {
            var tm = session.GetTowary();
            int dodano = 0;
            int zaktualizowano = 0;
            
            // Cały import w jednej transakcji
            using (var transaction = session.Logout(editMode: true))
            {
                foreach (var wiersz in dane)
                {
                    // Sprawdź czy towar istnieje
                    var towar = tm.Towary.WgKodu[wiersz.Kod];
                    
                    if (towar == null)
                    {
                        // Dodaj nowy
                        towar = new Towar();
                        tm.Towary.AddRow(towar);
                        towar.Kod = wiersz.Kod;
                        dodano++;
                    }
                    else
                    {
                        zaktualizowano++;
                    }
                    
                    // Ustaw/aktualizuj właściwości
                    towar.Nazwa = wiersz.Nazwa;
                    var cena = towar.Ceny["Hurtowa"];
                    cena.Netto = new DoubleCy(wiersz.Cena);
                }
                
                transaction.Commit();
            }
            
            session.Save();
            
            Console.WriteLine($"Import zakończony:");
            Console.WriteLine($"  Dodano: {dodano}");
            Console.WriteLine($"  Zaktualizowano: {zaktualizowano}");
        }
    }
    
    private List<DaneImportu> WczytajZPliku(string sciezka)
    {
        // Implementacja wczytywania z CSV/Excel...
        return new List<DaneImportu>();
    }
    
    private class DaneImportu
    {
        public string Kod { get; set; }
        public string Nazwa { get; set; }
        public decimal Cena { get; set; }
    }
}

Obsługa błędów

Wzorzec try-catch z sesją

public void BezpiecznaOperacja(Login login)
{
    using (var session = login.CreateSession(false, false, "Operacja"))
    {
        try
        {
            var tm = session.GetTowary();
            
            using (var transaction = session.Logout(editMode: true))
            {
                // Operacje na danych...
                var towar = new Towar();
                tm.Towary.AddRow(towar);
                towar.Kod = "TEST";
                
                transaction.Commit();
            }
            
            session.Save();
        }
        catch (Exception ex)
        {
            // Logowanie błędu
            Console.WriteLine($"Błąd: {ex.Message}");
            // Wyjątek przed Commit() = automatyczny rollback transakcji
            // Wyjątek z session.Save() = transakcja zatwierdzona w sesji, ale brak zapisu do bazy
            // Sesja zostanie automatycznie zwolniona przez using
        }
    }
}

Wzorzec z wieloma operacjami

public void WieleOperacji(Login login, List<string> kody)
{
    using (var session = login.CreateSession(false, false, "WieleOperacji"))
    {
        var tm = session.GetTowary();
        var bledy = new List<string>();
        
        foreach (var kod in kody)
        {
            try
            {
                using (var transaction = session.Logout(editMode: true))
                {
                    var towar = tm.Towary.WgKodu[kod];
                    if (towar != null)
                    {
                        towar.Delete();
                        transaction.Commit();
                    }
                }
            }
            catch (Exception ex)
            {
                bledy.Add($"{kod}: {ex.Message}");
                // Kontynuuj z następnym elementem
            }
        }
        
        session.Save();  // Zapisz udane operacje
        
        if (bledy.Any())
        {
            Console.WriteLine("Błędy: " + string.Join(", ", bledy));
        }
    }
}