Skocz do zawartości

[Sfera/SQL] Pola własne zaawansowane 2.0

Polecane posty

Sprawdzam Sobie zmiany obsług pól własnych w nowej wersji i potrzebuję kontrolnie odpowiedzi na kilka pytań.

Sfera v1

var towarPW = towarBO.Dane.PobierzEncjeZaawansowanychPolWlasnych();
var niebieski = sfera.PodajObiektTypu<ISlownikiWlasne>()["kolory"].Znajdz("niebieski").Dane;
towarPW.UstawWartoscPola("Poleslownikowe2", niebieski);

Sfera v2 - i tu zgłupiałem. To się aż tak bardzo skomplikowało? W sumie sam zapis jest na końcu, ale to co się zaczęło dział po środku nie nie ogarniam.

//pobranie wszystkich pozycji slownika
IZaawansowanePoleWlasne poleSlownikowe = zaawansowanePolaWlasne.PobierzZaawansowanePoleWlasne(typeof(Asortyment), "pz slownik");
var slownikWlasny = (ISlownikoweZrodloDanych<int, PozycjaSlownikaWlasnego>)poleSlownikowe.PobierzDefinicjeSlownika();
Dictionary<int, string> pozycjeSlownika = new Dictionary<int, string>();
foreach (PozycjaSlownikaWlasnego pozycja in slownikWlasny.UtworzZapytanieLinqTypowane())
  { pozycjeSlownika.Add(pozycja.Id, pozycja.Wartosc); }
//odczyt klucza obcego
int? kluczObcyDoWartosciSlownika = aso.Dane.PolaWlasneAdv2.Get<int?>("pz slownik");
if (kluczObcyDoWartosciSlownika.HasValue)
  {
  var biezacaPozycja = pozycjeSlownika.First(p => p.Key == kluczObcyDoWartosciSlownika);
  string biezacaWartosc = biezacaPozycja.Value;
  }
//zapis klucza obcego
var nowaPozycja = pozycjeSlownika.Last(); //dla przykładu wybieram ostatnią pozycję słownika
aso.Dane.PolaWlasneAdv2.Set<int?>("pz slownik", nowaPozycja.Key);     

SQL

Czy ta zmiana oznacza konieczność przepisania wszystkich raportów, gdzie odnośniki do bazy danych muszą mieć Adv2 na końcu?

Czy można pozostać przy starej wersji pól własnych?

Link to postu

Na szybko:

1) tak, trzeba będzie (najpóźniej do wersji wiosennej) dostosować rozwiązania własne wykorzystujące zaawansowane pola własne

2) można pozostać przy starych polach własnych, najdłużej do wiosny 2020. W wiosennej wersji planujemy automatyczne przejście na nowe pola własne. W wersji 27 dajemy taką opcję.

 

Pozwolę sobie skopiować część informacji o polach własnych z forum dla Partnerów InseRTu:

 

Nowe zaawansowane pola własne

W odpowiedzi na braki i problemy związane z funkcjonowaniem zaawansowanych pól własnych w obecnej postaci, podjęliśmy decyzję o stworzeniu nowego mechanizmu pól zaawansowanych. Ma on docelowo zastąpić mechanizm dotychczasowy.

Nowe pola własne są niekompatybilne ze starymi i potrzebna będzie migracja danych. Proces migracji istniejących baz będzie bezproblemowy poza przypadkami, gdy w podmiocie są zaawansowane pola własne i dodatkowo używane są wykorzystujące je rozwiązania własne/partnerskie (rozwiązania sferyczne, raporty LINQ, raporty SQL czy wydruki własne).
W takich przypadkach konieczne będzie dostosowanie tych rozwiązań do nowego mechanizmu.

W związku z koniecznością zmian w rozwiązaniach własnych przewidujemy rozłożenie w czasie procesu migracji podmiotów klienckich.


Zakładany harmonogram:

- jesień 2019 – (wersja 27) – dodanie do nexo dostępnej dla wszystkich opcji przejścia na nowe pola własne,
- wiosna 2020 – automatyczna migracja baz klienckich na nowy mechanizm.
Powyższy harmonogram oznacza, że jest około roku czasu na to by dostosować rozwiązana własne i dostarczyć je klientom. Oczywiście zachęcamy do szybszego zmierzenia się z tym problemem, tym bardziej, że nowe pola własne to także nowe możliwości.


Usprawnienia w nowej wersji zaawansowanych pól własnych:

- Brak rekompilacji modelu danych po zmianach w zaawansowanych polach własnych - wymagane jest jedynie ponowne uruchomienie nexo,
- Łatwiejsze tworzenie rozwiązań własnych ze względu na brak potrzeby kopiowania biblioteki InsERT.Moria.ModelDanych.dll po zmianach w zaawansowanych polach własnych,
- Zaawansowanemu polu własnemu można przypisać dowolną ilość unikatowych aliasów nazwy. Aby pobrać lub ustawić wartość w polu można użyć jego nazwy lub jednego ze zdefiniowanych aliasów. Pozwala to na wykorzystanie tego samego pola w różnych rozwiązaniach własnych, gdy każde z rozwiązań odwołuje się do pola pod inną nazwą,[/list]
- Wprowadzono słowniki własne SQL. W słownikach własnych SQL zbiór wartości pochodzi z wykonania zdefiniowanego zapytania SELECT,
- Typ "kwota" został zastąpiony bardziej uniwersalnym typem "liczba rzeczywista", dla którego można określić ilość miejsc po przecinku,
- Doszła możliwość określenia kolejności wyświetlania pól w oknie edycji pól własnych obiektu.

Jak wypróbować nowe pola własne

Aby przejść na nowe pola własne należy:
- przejść do modułu laboratorium (Ctrl + Space + XX) i wybrać opcję "PRZEJDŹ NA POLA WŁASNE W WERSJI 2."

Definiowanie w nexo pól własnych w nowej wersji:
1. W konfiguracji należy wybrać "System", a następnie wyszukać jeden z modułów:
- "Pola własne" - po jego wybraniu wyświetlone zostają wszystkie obiekty, dla których można definiować pola własne
- "Słowniki własne" - umożliwia wyświetlanie oraz dodanie/edycję/usunięcie słowników własnych i słowników własnych SQL
2. W konfiguracji zamiast "System" można także wybrać "Pola własne"


Użycie pól własnych w wersji 2 w rozwiązaniach własnych

1. W SDK do nexo znajduje się przykład "nexoPolaWlasne2", który pokazuje m.in.:
- W jaki sposób sprawdzić bieżącą wersję pól własnych (użycie interfejsu IWersjaPolWlasnych)
- W jaki sposób odczytać informacje o zdefiniowanych zaawansowanych polach własnych wersji 2. oraz słownikach własnych wersji 2. (użycie interfejsu IZaawansowanePolaWlasne oraz ISlownikiWlasne)
- W jaki sposób odczytać i ustawić wartości pól zaawansowanych wersji 2. w przykładowym obiekcie asortymentu
- W jaki sposób używać pól własnych w wersji 2. w zapytaniach LINQ
2. Mechanizm prostych pól własnych nie uległ zmianie - nie jest wymagana modyfikacja rozwiązania własnego, które korzysta tylko z prostych pól własnych
- nadal do pobrania informacji o prostych polach własnych można używać interfejsu IPolaWlasnePodstawowe - jednak tylko w zakresie dotyczącym prostych pól własnych (dla nowych rozszerzeń własnych zalecamy jednak używać nowego interfejsu IProstePolaWlasne)
- sposób odczytu i ustawiania wartości prostych pól własnych nie uległ zmianie
3. Rozwiązania własne korzystające z zaawansowanych pól własnych muszą zostać dostosowane do współpracy z wersją 2. Po konwersji podmiotu do pól własnych wersji 2., rozwiązanie własne które korzysta z zaawansowanych pól własnych w wersji 1. przestanie działać poprawnie.

Link to postu

Ok, to jeszcze wrócę do kwestii zmian, które będę musiał wprowadzić, a zapowiada się dla mnie gruby weekend :(

Sfera i  pole słownikowe

aso.Dane.PolaWlasneAdv2.Set<int?>("pz slownik", nowaPozycja.Key);     

Jeśli przerobiłbym Swoje rozwiązanie własne i przesyłał tutaj już właściwe ID ze słownika, to ten cały bajzel wcześniej mogę pominąć? ;) Obecnie mam taki króciutki kawałek kodu na to - przerobię to po Swojej stronie aby przekazywać w dictv już właściwy klucz z bazy danych.

// slownikowe
string dictk; string dictv; string dictn;
foreach(dynamic dict in results.dict) { 
  dictk = dict.k; dictn = dict.n; dictv = dict.v;
  var wartoscslownika = sfera.PodajObiektTypu<ISlownikiWlasne>()[dictk].Znajdz(dictv).Dane;
  towarPW.UstawWartoscPola(dictn,wartoscslownika); }

SQL

Struktura tych tabel będzie drastycznie inna, czy wystarczy, że dodam 2 na końcu i będzie działać? :) Odwołuję się do nich tylko około 100 razy w Swoim rozwiązaniu, ale za to w różnych zagmatwanych zapytaniach.

Link to postu
1 minutę temu, Andrzej Kulawik napisał:

Co do planów weekendowych

Spokojnie, nie powiedziałem, który! Będzie to dopiero weekend, w którym zdecydujemy się na przejście na nową wersję pól, a to nastąpi najwcześniej jak puścicie je w wersji pełnej. Nasz system jest tak bardzo powiązany z NEXO, że będzie do dla mnie wyzwaniem i chcę zebrać jak najwięcej informacji :)

Link to postu
Dnia ‎24‎.‎10‎.‎2019 o 09:11, Radomił Ząbik napisał:

Sfera v2 - i tu zgłupiałem. To się aż tak bardzo skomplikowało? W sumie sam zapis jest na końcu, ale to co się zaczęło dział po środku nie nie ogarniam.

W SDK do nexo znajduje się przykład "nexoPolaWlasne2", który pokazuje wszystkie możliwości API dostępowego do nowych pól własnych. Fragment kodu, który przytoczył Pan na początku tego postu pochodzi właśnie z przykładu "nexoPolaWlasne2". Jest on długi, dlatego że pokazuje wszystkie możliwości pracy ze słownikiem czyli odczyt wszystkich wartości słownika, odczyt klucza obcego z pola i zapis klucza obcego w polu.

Oczywiście w realnym rozwiązaniu własnym można to skrócić, a więc w Pana przypadku:

zamiast:

var towarPW = towarBO.Dane.PobierzEncjeZaawansowanychPolWlasnych();
var niebieski = sfera.PodajObiektTypu<ISlownikiWlasne>()["kolory"].Znajdz("niebieski").Dane;
towarPW.UstawWartoscPola("Poleslownikowe2", niebieski);

będzie:

var poleSlownikowe2 = zaawansowanePolaWlasne.PobierzZaawansowanePoleWlasne<Asortyment>("Poleslownikowe2");
var slownikWlasny = (ISlownikoweZrodloDanych<int, PozycjaSlownikaWlasnego>)poleSlownikowe2.PobierzDefinicjeSlownika();
var pozycjaNiebieska = slownikWlasny.UtworzZapytanieLinqTypowane().First(p => p.Wartosc == "niebieski");
towarBO.Dane.PolaWlasneAdv2.Set<int?>("Poleslownikowe2", pozycjaNiebieska.Id);

Jeśli chodzi o pętlę, to będzie analogicznie:

zamiast:

string dictk; string dictv; string dictn;
foreach(dynamic dict in results.dict) { 
	dictk = dict.k; dictn = dict.n; dictv = dict.v;
	var wartoscslownika = sfera.PodajObiektTypu<ISlownikiWlasne>()[dictk].Znajdz(dictv).Dane;
	towarPW.UstawWartoscPola(dictn,wartoscslownika); }

będzie:

string dictk; string dictv; string dictn;
foreach(dynamic dict in results.dict) { 
	dictk = dict.k; dictn = dict.n; dictv = dict.v;
	var poleWlasne = zaawansowanePolaWlasne.PobierzZaawansowanePoleWlasne<Asortyment>(dictn);
	var slownikWlasny = (ISlownikoweZrodloDanych<int, PozycjaSlownikaWlasnego>)poleWlasne.PobierzDefinicjeSlownika();
	var wartoscslownika = slownikWlasny.UtworzZapytanieLinqTypowane().First(p => p.Wartosc == dictv);
	towarBO.Dane.PolaWlasneAdv2.Set<int?>(dictn, wartoscslownika.Id); }

 

Edytowane przez Łukasz Kubacki
  • Dziękuję 1
Link to postu

Wystarczył ten pierwszy kawałek, nie musiał Pan mojego "syfiastego" kodu poprawiać ;)

To tylko jeszcze pytanie, co z SQLem, czy na strukturę tabel spadła jakaś mocna bomba w związku ze zmianą na 2.0 - przepraszam, że pytam, a nie grzebie po bazach, ale mógłbym coś przegapić ;)

Link to postu
4 minuty temu, Radomił Ząbik napisał:

To tylko jeszcze pytanie, co z SQLem, czy na strukturę tabel spadła jakaś mocna bomba w związku ze zmianą na 2.0 - przepraszam, że pytam, a nie grzebie po bazach, ale mógłbym coś przegapić ;)

Tak, pola własne v2 są przechowywane całkowicie inaczej w bazie niż pola v1

Link to postu
  • 3 miesiące temu...

Dotychczasowy harmonogram przewidywał:

Cytat

- wiosna 2020 – automatyczna migracja baz klienckich na nowy mechanizm.

 

W wersji wiosennej (30) (koniec marca) staną się następujące rzeczy:

9293feeb0183c67ea1ea8c52f0dbaf8c.gif podmioty utworzone w wersji 30 lub wyższej będą od razu działały z włączonymi polami zaawansowanymi v2
9293feeb0183c67ea1ea8c52f0dbaf8c.gif podmioty konwertowane z wersji wcześniejszej do 30, które nie posiadają żadnych pól zaawansowanych, od wersji 30 będą działały z włączonymi polami v2
9293feeb0183c67ea1ea8c52f0dbaf8c.gif podmioty konwertowane z wersji wcześniejszej do 30, które posiadają pola zaawansowane, pozostaną w trybie pól v1, przy czym:
- przycisk przejścia na pola v2 stanie się ogólnie dostępny dla wszystkich użytkowników
- użytkownicy będą zachęcani do przejścia na pola v2 (m.in. z sugestią wcześniejszego skontaktowania się z Partnerem/Serwisantem)

Powyższe oznacza, że użytkownicy z zaawansowanymi polami własnymi będą mogli odroczyć migrację na pola własne v2 do wersji 31 (czerwiec/lipiec 2020), kiedy to nastąpi automatyczna migracja.

Link to postu

Odczytywanie i zapisywanie wartości zaawansowanych pól własnych v2 od wersji 29 nexo

W wersji 29 nexo wprowadziliśmy prostszy sposób na odczytywanie i zapisywanie wartości zaawansowanych pól własnych v2. Nowy sposób ma za zadanie ułatwić odczyt/zapis wartości dla pól typu "Słownik własny", "Słownik własny SQL" oraz "Słownik systemowy".

Przykładowo, jeżeli dla Asortymentu zdefiniowano pole własne typu "Słownik własny" o nazwie "pz slownik", wtedy aby odczytać lub zapisać wartość tego pola będzie można zrobić tak:

using (Uchwyt sfera = UruchomSfere())
{
    IAsortymenty asortymenty = sfera.PodajObiektTypu<IAsortymenty>();
    IAsortyment aso = asortymenty.Znajdz("T1");

    IPolaWlasneAdv2Accessor asoPW2Accessor = sfera.UtworzPolaWlasneAdv2Accessor(aso.Dane);

    //odczyt biezacej wartosci pola  
    var biezacaPozycja = asoPW2Accessor.PobierzWartoscTypuSlownikWlasny("pz slownik");
    if (biezacaPozycja != null)
    {
        int biezacyKlucz = biezacaPozycja.Klucz;
        string biezacaWartosc = biezacaPozycja.Wartosc;
    }

    //pobranie wszystkich pozycji slownika  
    var pozycjeSlownika = asoPW2Accessor.PobierzWartosciTypuSlownikWlasny("pz slownik");
    foreach (var pozycja in pozycjeSlownika)
    {
        int klucz = pozycja.Klucz;
        string wartosc = pozycja.Wartosc;
    }

    //zapis nowej wartosci pola (dla przykładu wybieram ostatnią pozycję słownika)  
    var nowaPozycja = pozycjeSlownika.Last();
    asoPW2Accessor.UstawWartoscTypuSlownikWlasny("pz slownik", nowaPozycja.Klucz);
}

Metoda sfera.UtworzPolaWlasneAdv2Accessor(encja) przyjmuje encję, która posiada zaawansowane pola własne v2. Metoda ta zwraca obiekt, który umożliwia odczyt i zapis wartości pól z tej encji.

Odczytanie i zapis wartości pól typu "Słownik własny SQL" i "Słownik Systemowy" odbywa się w analogiczny sposób. Odpowiednie przykłady znajdą Państwo w dokumentacji do sfery v29 w pliku InsERT.nexo.Sfera.chm (gałąź "Rozszerzanie/Pola własne/Pola własne w wersji 2").

Nowy sposób odczytu/zapisu wartości można zastosować do pól zaawansowanych wszystkich typów, nie tylko typów słownikowych.
Przykładowo, jeśli dla asortymentu zdefiniowano następujące pola:
1. pole typu "Tekst" o nazwie "pz tekst"
2. pole typu "Liczba całkowita" o nazwie "pz int"
3. pole typu "Liczba rzeczywista" o nazwie "pz decimal"
4. pole typu "Wartość logiczna" o nazwie "pz bool"
5. pole typu "Data" o nazwie "pz data"
Wtedy odczyt/zapis wartości tych pól wygląda następująco:

using (Uchwyt sfera = UruchomSfere())
{
   IAsortymenty asortymenty = sfera.PodajObiektTypu<IAsortymenty>();
   IAsortyment aso = asortymenty.Znajdz("T1");

   IPolaWlasneAdv2Accessor asoPW2Accessor = sfera.UtworzPolaWlasneAdv2Accessor(aso.Dane);

   string pzTekst = asoPW2Accessor.PobierzWartoscTypuTekst("pz tekst"); //odczyt
   asoPW2Accessor.UstawWartoscTypuTekst("pz tekst", "abcd"); //zapis

   int? pzInt = asoPW2Accessor.PobierzWartoscTypuLiczbaCalkowita("pz int"); //odczyt
   asoPW2Accessor.UstawWartoscTypuLiczbaCalkowita("pz int", 5); //zapis

   decimal? pzDec = asoPW2Accessor.PobierzWartoscTypuLiczbaRzeczywista("pz decimal"); //odczyt
   asoPW2Accessor.UstawWartoscTypuLiczbaRzeczywista("pz decimal", 1.23m); //zapis

   bool? pzBool = asoPW2Accessor.PobierzWartoscTypuLogicznego("pz bool"); //odczyt
   asoPW2Accessor.UstawWartoscTypuLogicznego("pz bool", true); //zapis

   DateTime? pzData = asoPW2Accessor.PobierzWartoscTypuData("pz data"); //odczyt
   asoPW2Accessor.UstawWartoscTypuData("pz data", DateTime.Now); //zapis
}

 

  • Dziękuję 1
Link to postu

Pana poprzednie przykłady:

Dostęp do pól v1:

var towarPW = towarBO.Dane.PobierzEncjeZaawansowanychPolWlasnych();
var niebieski = sfera.PodajObiektTypu<ISlownikiWlasne>()["kolory"].Znajdz("niebieski").Dane;
towarPW.UstawWartoscPola("Poleslownikowe2", niebieski);

Dostęp do pól v2 od wersji 29 nexo:

var towarPW = sfera.UtworzPolaWlasneAdv2Accessor(towarBO.Dane);
var niebieski  = towarPW.PobierzWartosciTypuSlownikWlasny("Poleslownikowe2").First(p => p.Wartosc == "niebieski");
towarPW.UstawWartoscTypuSlownikWlasny("Poleslownikowe2", niebieski.Klucz);

Dostęp do pól v1:

string dictk; string dictv; string dictn;
foreach(dynamic dict in results.dict) { 
	dictk = dict.k; dictn = dict.n; dictv = dict.v;
	var wartoscslownika = sfera.PodajObiektTypu<ISlownikiWlasne>()[dictk].Znajdz(dictv).Dane;
	towarPW.UstawWartoscPola(dictn,wartoscslownika); }

Dostęp do pól v2 od wersji 29 nexo:

var towarPW = sfera.UtworzPolaWlasneAdv2Accessor(towarBO.Dane);
string dictk; string dictv; string dictn;
foreach(dynamic dict in results.dict) { 
	dictk = dict.k; dictn = dict.n; dictv = dict.v;
	var wartoscslownika = towarPW.PobierzWartosciTypuSlownikWlasny(dictn).First(p => p.Wartosc == dictv);
	towarPW.UstawWartoscTypuSlownikWlasny(dictn, wartoscslownika.Klucz); }

 

Edytowane przez Łukasz Kubacki
poprawki
  • Dziękuję 1
Link to postu

Wielkie dzięki, za wprowadzone zmiany! Zdjęło to zdecydowanie mocno obawy przed konwersją od strony Sfery :) Pozostaje teraz konwersja odnośnie zapytań do baz danych, i tutaj pytanie - czy macie opis struktury powstawania kolumn w tabeli bazy danych, dla nowej wersji? W v1 powstawały one z uproszczenia pierwszej wprowadzonej nazwy. W wersji v2, z tego co wstępnie udało mi się sprawdzić na pobocznym podmiocie, macie zapis np. S0 - czyli pierwsze pole typu string, S1 itd.

Link to postu
Cytat

Pozostaje teraz konwersja odnośnie zapytań do baz danych, i tutaj pytanie - czy macie opis struktury powstawania kolumn w tabeli bazy danych, dla nowej wersji?

Aktualnie nie mamy opisu struktury kolumn dla "użytkowników". W najbliższym czasie postaram się napisać jak to wygląda.

Cytat

W wersji v2, z tego co wstępnie udało mi się sprawdzić na pobocznym podmiocie, macie zapis np. S0 - czyli pierwsze pole typu string, S1 itd.

Dobrze Pan zauważył

  • Dziękuję 1
Link to postu
1 godzinę temu, Łukasz Kubacki napisał:

Aktualnie nie mamy opisu struktury kolumn dla "użytkowników". W najbliższym czasie postaram się napisać jak to wygląda.

To czekam z niecierpliwością, jak bardzo mam "przesrane" z zapytaniami do bazy SQL. Bez funkcji na rzutowanie nazw pól tego nowego nazewnictwa chyba się nie obejdzie, gdyż ja mam jeden kluczowy problem z największą integracją, którą opracowałem - działa ona obecnie już na 6 podmiotach jednocześnie. Na tą chwilę, z polami własnymi v1 nie było problemu bo w każdej bazie nazywałem je tak samo i nieważne, że w jednej to pole było, a w drugiej nie, nie stanowiło to problemu. Nowa struktura, nie zapewni tej 100% jednolitości we wszystkich bazach, więc trzeba będzie to omijać. Podobnie raporty SQL skopiowane między podmiotami, będą bezużyteczne. A tak ogólnie, to jaką kolejność przyjmiecie przy konwersji v1 na v2, nadawania pól S0, S1, S2 ... ?

Link to postu
  • 3 miesiące temu...

W ramach wrażeń, po przerzuceniu największych sferycznie zintegrowanych podmiotów, na pola własne 2.0, mam w sumie tylko parę uwag/pytań:

- PolaWlasneAdv2Accessor to podstawa i bez niego wdrożenie było by zdecydowanie utrudnione. Intryguje jedynie nazewnictwo zmiennych - Klucz to w sumie Id, w przypadku słowników, więc taka trochę różnica względem całego systemu.

- brakuje dawnych "aliasów", które tworzyły się nijako jako nazwy kolumn w starej strukturze. O ile przy rozwiązaniach własnych, można to Sobie zmapować, o tyle podczas obsługi raportów jest to masakryczne i rozwala całkowicie możliwość swobodnego przerzucania raportów pomiędzy podmiotami

- czy w związku z okresem przejściowym (kompatybilność z starymi polami), konieczne jest załączanie InsERT.Moria.ModelDanych.dll z deployments podmiotu - przy kompilowaniu wielu rozwiązań, dla wielu podmiotów, wygodnie było by już korzystać tylko z bibliotek z SDK.

Link to postu
  • 2 tygodnie później...

Ok, mam drobne, aczkolwiek bardzo ważne pytanie - Jak ustawić wartość słownikową na pustą?

- przesłanie do PobierzWartosciTypuSlownikWlasny wartości pustego stringa, wywala błąd

- przesłanie do UstawWartoscTypuSlownikWlasny jako wartość null, także wywala błąd

Skończyły mi się pomysły :(

Link to postu
×
×
  • Dodaj nową pozycję...