- Honor Magic5 Pro - kamerák bűvöletében
- Poco X3 Pro - hardverfrissítés
- NFC Ring, avagy gyűrű, amivel fizetni is lehet
- Prohardver app (nem hivatalos)
- Milyen okostelefont vegyek?
- Csak semmi szimmetria: flegma dizájnnal készül a Nothing Phone (3)
- Magisk
- Telekom mobilszolgáltatások
- iPhone topik
- One mobilszolgáltatások
Új hozzászólás Aktív témák
-
joysefke
veterán
válasz
Tomi_78 #10149 üzenetére
Köszi, tehát a Count-1. Csak azt furcsállom, hogy olyan különösen viselkedik ezzel, ha másik névtérbe viszem át egy változóban a Count-1 értéket, mint most az elhelyez alprogramba, mert minden tankot elmozdít.
Próbáld meg debuggerrel megnézni, hogy mi a baj.
de az nem olyan egyszerű, ha eltérő a képek mérete.
A programodban felhasznált képeket igazítsd a programod követelményeihez és ne a programodat a képekhez. Szerintem a tankoknak meg minden entitásnak általad előre meghatározott mérete kéne legyen és ehhez a mérethez kéne a tank képét hozzáigazítanod.
Ha esetleg nem ismered, akkor itt tudsz inspirálódni:
Neon shooter:
https://github.com/MonoGame/MonoGame.Samples/tree/3.8.0/NeonShooter
tutorial:
https://code.tutsplus.com/make-a-neon-vector-shooter-in-xna-basic-gameplay--gamedev-9859tPlatformer:
https://github.com/MonoGame/MonoGame.Samples/tree/3.8.0/Platformer2D -
joysefke
veterán
válasz
Tomi_78 #10147 üzenetére
A Count megadja a List<T> aktuális elemszámát. Ha mindig a végéhez adod hozzá az újabb elemet (tehát nem beszúrsz) akkor a Count-1 fogja megadni az utolsónak hozzáadott elem indexét vagy -1-et ha nincsen még benne elem.
Debuggolni próbáltad már a programodat hogy megtaláld a hibát?
Ha a tank leesésére az animáció miatt van szükséged, az érthető. Ha viszont így akarod megkapni az induló Y koordinátáját az számomra fura. A platform elemednek van egy pozíciója az Y tengely mentén, van magassága, a tanknak is van kiterjedése ebből előre ki tudod számítani, hogy mi lesz a tank Y koordinátája.
Mondjuk én tuti úgy oldanám meg a platfom elemeket, hogy azok egy egy mezőt teljesen elfoglaljanak, tehát játék kezdetekor a pályarajz alapján triviális legyen, hogy a mozgó elemeknek mi az Y koordinátájuk.Az ütközésdetektálási kód (nem próbáltam meg értelmezni) nem tűnik bombabiztosnak, illetve nem látom, hogy miért kell neked téglalapok ütközésének detektálásához kódot írnod? A frameworkben amiben dolgozol nincsen Rectangle osztály aminek lenne bool Intersects(Rectangle other) metódusa?
-
joysefke
veterán
válasz
(ex)Cat #10116 üzenetére
Gondolom az a baj, hogy speciális karakter van a stringben és az nincsen megfelelően escapelve.
elsőnek sima "verbatim" stringkonstansként próbálnám megadni:
var format = @"_-* # ##0\ _F_t_-;-* # ##0\ _F_t_-;_-* ""-""??\ _F_t_-;_-@_-";
itt annyi történt, hogy a sztringen belüli dupla aposztróf karaktert megdupláztam, mert azt még verbatim sztringen belül is escapelni kell.
ha ez sem megy, akkor próbáld meg raw stringként, ahol is tripla-duplaaposztróf között van a sztring.
var format = """_-* # ##0\ _F_t_-;-* # ##0\ _F_t_-;_-* "-"??\ _F_t_-;_-@_-""";
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/verbatim
-
joysefke
veterán
válasz
Tomi_78 #10110 üzenetére
A képlet első ránézésre jónak tűnik. Próbálj írni pár tesztesetet amelyek általad előre kiszámolt eseteknek a képlet által visszaadott végeredményét tesztelik az általad elvárttal szemben. Aztán ha valami nem stimmel, akkor addig kalapálod a képletedet amíg végül az összes teszteseted zöld nem lesz.
Legalább minden negyedre ([0°-90°], [90°-180°], stb ) jusson egy teszteset. A -90° a +270°-el egyenértékű a képeden. -90 mod 360 = 270 mod 360. Tehát itt a -90 nem egyenlő +90-nel.
-
joysefke
veterán
válasz
martonx #10100 üzenetére
Remélhetőleg valahol látszódni fog a useren, hogy min keresztül lépett be.
Erre a ClaimsPrincipal-on egészen biztosan lesz egy claim amit a HasClaim(claimType)-pal vagy valami hasonlóval lehet ellenőrizni.
Elsőre elég lehet egy if az onGetAccountban,
Azért érdemes a framework által biztosított auth check módszert használni, mert ha nem teljesül a policy, akkor a pipelineban a végrehajtás el sem jut addig hogy meghívódjon a Controller action method (gondolom Razornél is valami hasonló van annotálva), így hibázni sem tudsz és nem is kell a hiba kezelésével (redirect vagy error code) foglalkoznod.
-
joysefke
veterán
válasz
martonx #10097 üzenetére
Én sem ismerem, hogy Razor-ban ez hogy van (vagy úgy általában a Razort), de feltételezem, hogy "claim" alapon könnyen megvalósítható az authorizáció, ahol végül [Authorize(Policy = "policyName")] attribútummal lenne dekorálva a top level Razor metódus.
A "policyName" policy pedig az ASP NET Core "User" claimjeit ellenőrzi. Az adott Identity Provider (Spotify) által történt azonosításra nyilván a Useren (ClaimsPrincipal-on) belül fog utalni egy claim érték, amit az adott policy ellenőrizni tud.
https://learn.microsoft.com/en-us/aspnet/core/security/authorization/claims?view=aspnetcore-8.0
-
joysefke
veterán
válasz
Tomi_78 #10091 üzenetére
Amúgy csupán memóriatakarékossági okból lett volna szükségem a byte típusra, mert az id és idk nem lett volna több a programban, mint 255.
Ezért mondtam, hogy érdemes lenne valami alapozó könyvet olvasgatni. Egyébként addig nincs értelme optimalizálgatni, amíg arra nincs szükség (, illetve amíg nem tudod mit csinálsz).
A programodban biztos lehetsz benne, hogy az hogy a MainForm ban egy fieldnek bool-t használsz int helyett semmi jelentősége nincsen illetve egyetlen byte-ot sem spórolsz, a MainForm byte-re pontosan ugyanakkora lesz.
Ennek az oka, hogy az objektumok fieldjei a memóriában nem feltétlenül teljesen folytonosan helyzkednek el, hanem igazítva vannak.class MyClass
{
byte B;
int Num;
}Ez például jó eséllyel a "Num" 4byteos mérete miatt 4 bytejával lesz igazítva, tehát a B is 4 byteot fog elfoglalni jó eséllyel. (futtatókörnyezet függő). Az 1byte hasznos terület után lesz 3byte foghíj. Sebességben sincsen semmi különbség két byte összeadása illetve két integer összeadása között. (Nem mintha ez bármit számítana)
De ezekkel egyelőre nincs értelme foglalkoznod.
-
joysefke
veterán
válasz
Alexios #10086 üzenetére
Magyarázhatsz neki. Ha elolvas valamit, azt nem azért teszi, hogy a hasznos tudását növelje, hanem muníciót gyűjt a következő hónapok kötekedéséhez, ahol a "profi programozókat" (az ő szava járása) szapulja akik valami fontosnak vélt dolgot nem jól tudnak.
Ha az elmúlt éveket nem trollkodással töltötte volna, akkor akár "profi programozó" programozó is lehetne ami nyilván mindig is lenni akart. -
joysefke
veterán
válasz
Tomi_78 #10078 üzenetére
Valami alapozó könyvet kellene olvasnod, hogy helyére kerüljenek a dolgok.
A "new" utasítással példányosítottál egy osztályt, az objektum a (heap) memóriában jött létre, a var kulcsszóval deklarált változód a stacken van (a futó metódus scopeján belül) ez a változó egy referencia ami a heapen lévő objektumra mutat. A referencián keresztül tudod elérni és használni a heapen lévő objektumodat.A var -ral deklarált változód típusa már kódszerkesztési időben ismert a fejlesztőkörnyezet számára. Ha a fejlesztőkörnyezet nem tudja a típust eldönteni, akkor be fogja azt a kódrészt pirosítani.
A var csak arra van, hogy neked kényelmesebb legyen, ne kelljen a hosszú típusnevet kiírni, illetve refaktorálásnál is előnyös lehet.var myObject = new MyClass(); esetén a myObject típusa "MyClass típusú referencia";
-
joysefke
veterán
1,
Mi az, hogy "keresztbe példányosítás"?
Ha öröklődéssel hoznál létre egy körkörös dependenciát (származtatott osztály ugye függ az ősosztályától), azt kódszerkesztési időben észrevenné a VS és nem tudsz eljutni oda, hogy futni tudjon a kódod és kivételt kapj mivel le sem forg fordulni. Tehát nem ez a hiba.2,
Tehát akarsz egy ilyet:SQLiteService : CommonService { ...}
Aztán paraméter nélküli konstruktorral szeretnéd példányosítani:
SQLiteService()
Itt kódszervezési probléma van. Az ASP Net Core fő szervezési koncepciója a Dependency Injection. Mivel user kódot írsz és itt most nincsenek egyéb megfontolások ezért ezt az esetedben konstruktorral történő injekciót kéne jelentsen.
A Te SQLiteService osztályod azt állítja magáról, hogy ő nem függ senkitől és semmitől. Ami nonszensz.
Próbáld ki, csinálj egy unit teszt projektet, add hozzá az ASPs projektedet mint függőség és próbáld meg unit tesztből példányosítani és használniSQLiteService
-t.Nyilván nem fog menni, mert szükség lenne az SQLite fájl útvonálára minimum, ami viszont konfigurációból (illene) jöjjön.
3,
Loggolás ugyanez pepitában.ASP-ben a loggolás legegyszerűbb módja DI-jon keresztül van:
Logging in .NET Core and ASP.NET Core | Microsoft LearnSzerintem az a baj, hogy a szervizeidben rejtett, implicit függőségek vannak amelyeket nem derítettél fel.
-
joysefke
veterán
WindowsIdentity-vel kapcsolatban szeretnék segítséget kérni. Nem értek hozzá, eddig nem kellett ezzel foglalkoznom. Világítsatok rá, ha valami valahol technikailag nem megoldható.
1, van egy applikáció ami egy lokál service account "LOCALPC\MyService" nevében fut.
ennek az accountnak igény szerint tudok jogosultságokat adni.2, Elő kell állítanom egy WindowsIdentity objektumot ami egy domain usert személyesít meg: DOMAIN1\Pisti . Ezt a WindowsIdentity objektumot egy belső API használja. Úgy gondolom, hogy nem imperszonálásra, csupán a usert érintő AD security releváns információk megnézésére. Ebben nem vagyok biztos.
3, Az applikáció rendelkezik a domain admin user/pwd párosával "DOMAIN1\Administrator" + Pwd (igen, ez már eredetileg egy ilyen applikáció
) Pistiével és a többi userével viszont nem.
Tehát szeretnék DOMAIN1\Pistike nevére előállítani az applikációban egy WindowsIdentity objektumot.
Nem tudom, hogy ez egyáltalán lehetséges-e.
4, Létezhet-e WindowsIdentity objektum a LOCALPC-n DOMAIN1\Pisti nevére anélkül, hogy a LOCALPC a DOMAIN1-ben lenne? Jelenlegi környezetemben a LOCALPC bent van a domainben, de az appot futtató account nincsen.
5, Hogyan tudom megvalósítani? Nem akar összejönni, bár ez nem csoda, mert nincs vele tapasztalatom?
Azt látom, hogy ha "DOMAIN1\Administrator" futtat kódot, akkor
new WindowsIdentity(string: DOMAIN1_Pisti_upn)
konstruktorral tudok érvényes és az app számára használható WindowsIdentity objektumot létrekozni. Pisti nevére Pisti pwd-je nélkülAz is működik, hogy LOCALPC\MyService futtatja a kódot és bejelentkezteti a DOMAIN1\Administrator-t username/pwd-vel
advapi32.dll.LogonUser(lpszUsername, lpszDomain, string lpszPassword, dwLogonType, dwLogonProvider, out phToken)
-en keresztül. Itt végül visszakapok egy WindowsIdenity a DOMAIN1\Administrator nevére és úgy tűnik, hogy imperszonálásra is tudom használni, de anew WindowsIdentity(string: DOMAIN1_Pisti_upn)
hívás így is elbukik. Az alábbi hibaüzenettel:Error Message: Test method ApiSandbox.ImpersonationSandbox.Test2 threw exception: System.DllNotFoundException: Unable to load DLL 'secur32.dll': Either a required impersonation level was not provided, or the provided impersonation level is invalid. (Exception from HRESULT: 0x80070542) Stack Trace: at System.Security.Principal.WindowsIdentity.KerbS4ULogon(String upn, SafeAccessTokenHandle& safeTokenHandle) at System.Security.Principal.WindowsIdentity..ctor(String sUserPrincipalName, String type) at System.Security.Principal.WindowsIdentity..ctor(String sUserPrincipalName) at ApiSandbox.ImpersonationSandbox.Test2() in C:\...\ImpersonationSandbox.cs:line 48
Az eleje, az "Unable to load DLL 'secur32.dll'" biztosan nem stimmel. Ugyanazt a tesztkódot domain-adminként elindítva lefut.
Van ezzel a témával kapcsolatban valami jó anyag?
-
joysefke
veterán
válasz
bandi0000 #9945 üzenetére
Ahogy már írták a DbContext már önmagában is repository és unit of work.
Innen kezdve ha becsomagolod egy generikus repository + UoW absztrakcióba, akkor azt nem a funkcionalitás miatt teszed, hanem hogy elfedd a EntityFramework-öt, tehát hogy a repositoryt használó kód ne tudja magát az adott EfCore verzióhoz/funkciókhoz láncolni.
akkor van valami köztes réteg még a felület és az adatbázis közt, ami pl olyan feladatot látna el, hogy mentéskor ha ügyfelet és autót akarunk menteni, akkor a felületen kb csak annyi hívás legyen, hogy: SaveClientWithCar(Client client, Car car) és ez a köztes réteg lezongorázza a mentéseket ID generálással és beállítással?
Igen, a repository egy low level absztrakció az adathozzáférési rétegben.
Ha van egy featuröd (amit mondjuk egy UI page valósít meg) akkor annak a featurenek lesz konkrét igénye hogy adatokat tudjon olvasni a DB-ből (amit megjelenít a user számára) illetve a user által módosított adatokat perzisztálni tudja DB-be.
Az adatok formájára nézve a feature nyilván konkrét kívánalmakat fogalmaz meg. (e.g. mutasd az összes usert akinek van autója az autója típusával és évjáratával együtt) illetve meghatározza, hogy melyik adatmorzsa módosítható és melyik nem a feature kontextusában.Itt érdemes egy a featuret kiszolgáló, a repositorynál magasabb absztrakciós szinten lévő, data access service osztályt definiálni ami a repositoryra támaszkodva keríti elő a featuret hajtó kód számára az adatokat illetve menti el a változásokat. A repository-ból visszaadott adatokat arra a formára tudja adaptálni amilyen formában a featurnek szüksége van rá.
egy alternatíva lehet, hogy hagyod a repository patternt és ezeket az adott featuret kiszolgáló data access service osztályokat közvetlenül az Ef DbContext-re építed (DI-t használva nyilván) aztán a featuret hajtó logika használja ezeket (ezek interfészét).
-
joysefke
veterán
ezeket próbáltad?
WebApplication and WebApplicationBuilder in Minimal API apps | Microsoft LearnMásik opció hogy appsettings.json-ban definiálod a portot.
-
joysefke
veterán
Nem párhuzamosítást, hanem asszinkronitást keresel. A UI-ok általában úgy működnek, hogy egyetlen, dedikált szál tudja a UI-on lévő controllokat updatelni, minden más szálból (pld egy background thread) történő update exceptiönnel végződik.
Ha a UI -threaden blokkolsz (a UI event által triggerelt kód nem másik threaden fut, vagy a UI threadet kényszeríted IO-ra várakozásra) akkor megfagy a UI egészen addig amíg a UI thread fel nem szabadul.
Arra hogy hogyan tudod a munkát egy másik szálra átvinni majd az eredményt a UI threadnek visszaadni arra a Task-Async-Pattern (async -await) való. Vannak más régi megvalósítások is. Keress async-await példát, elég egyszerű a használata.
(Nincs dolgom UI-al, de ez kb általános kell legyen, tehát a Winforms-ra is vonatkozik).
szerk:
A fent említett IProgress is egyébként egy ilyen megvalósítás. A progress reportot átküldi a UI threadre -
joysefke
veterán
válasz
CPT.Pirk #9919 üzenetére
A projekt számára hatalmas pozitív lépés lenne, ebből a TryPop hozzáadott értéke szerintem nulla.
Egy üres konzol projektet triviális upgradelni NET6-ra, (átírsz a csproj-ban egy sort) egy nagy applikációt viszont nem lesz ilyen egyszerű.
Ha van .NET fejlesztő aki ezt főműsorban fejleszti, azt meg lehetne kérdezni, hogy ez miért nem történt még meg.
-
joysefke
veterán
válasz
CPT.Pirk #9911 üzenetére
Ilyenkor mi van?
Használod a Peek-etvagy updatelsz .NET 6-ra (Standard 2.1-re)
Netes példákban én is láttam ezeket, de nem írták, hogy valamit kellene hozzájuk bekapcsolni.
1,
A MS-nak egész jó online C# / .NET doksija van /learn.microsoft.com/. Első körben, ha full homály valaminek a működése, akkor azt érdemes megnézni.
Queue<T>.Peek Method (System.Collections.Generic) | Microsoft LearnA bal felső sarokban a drop-downból ki is tudod választani, hogy mi a target framework verziója.
2,
Sajnos nem készült dokumentáció a kódról pár soros szösszeneteken túl, így a "mire gondolt a költő" helyzet van mikor nézem mi lehet a gond.Ha ténylegesen meg kell értened hogy mit csinál az a metódus amit belinkeltél, akkor mivel tiszta függvénynek tűnik és fontos logikát kódol (tehát minimális befektetéssel tudsz hasznos tesztet írni), ezért a legjobb amit tehetsz, ha írsz rá unit-teszteket, azt könnyű futtatni, debuggolni, ezért egyszerre tudod megérteni és kikupálni a függvényt.
Ehhez persze az kéne, hogy a unit teszt vagy elérje a metódust /A/ vagy a metódus ne az osztályban legyen deklarálva /D/, vagy objektumként /B/ vagy delegate-ként /C/ átadva, így tesztelhetővé válik.
-
joysefke
veterán
válasz
CPT.Pirk #9904 üzenetére
A leírásod arra utalt, hogy még "látod", hogy van benne elem és úgy dob exceptiönt.
Debug buildben látnod kellett volna a ciklus fején a feltétel ellenőrzése előtt hogy üres a stack -kurzort fölé viszed-.Ha az a baj, hogy kifogyott a Queue, akkor éppen berakhatsz egy (Count > 0) && -t a feltétel elejére vagy Peek() helyett TryPeek(out string)-kel dolgozol.
if (s1.TryPeek(out string item) && item != "&&" && item !="||" )
{
s1.Pop();
}
-
joysefke
veterán
-
joysefke
veterán
Robot porszívó programozás?
Ez lenne az?
Google Coding Interview Question | Leetcode 489 | Robot Room Cleaner - YouTube -
joysefke
veterán
válasz
Alcsi69 #9864 üzenetére
Én "hobbiból" végigcsináltam ezt a Blazor intro könyvet : Blazor in Action (manning.com) . (hobbiból mivel front end ambícióim nincsenek).
A példaprogram kifejezetten jó a könyv jól követhető, jól van felépítve. Kliens oldali (Web Assembly) konfigurációt használ a végigvezetett példa, de szerver oldali Blazorral is ugyanígy működne.
Én ha saját szórakoztatásomra Blazor projektet csinálnék elsőnek szerver oldali Blazorral indulnék el, tehát nem WebAssembly-vel. Nehézkesebb volt a debuggolás mint tradícionális .NET runtimeon futó projektek esetén.
Blazor Serverrel fog működni a debuggolás és úgy általában a tooling. Szerintem ez utóbbi magas prioritás kell legyen. ASP.NET Core Blazor hosting models | Microsoft LearnErdemes lehet a C#-ot megtanulgatni.
Érdemes. Ha a legkissebb ellenállás irányában akarsz menni, akkor valami bejáratott, nagy népszerűségnek örvendő framework körül építkeznél. Mondjuk ASP Net Core: rengeteg jó anyag, tooling és még álláshírdetésben is fogsz vele találkozni.
Persze nyilván a feladat határozza meg az eszközt és nem fordítva. -
joysefke
veterán
Éles C# projektben próbálkozott már valaki funkcionális megvalósítással?
Ezt a könyvet olvasom: Functional Programming in C#, Second Edition (manning.com)
és eddig kb mindenre van válasza. (Adatbázisnál érzem azt, hogy bizonyos helyzetekben egy append-only DB csak bonyolítana a dolgon, esetleg nehezítené DB oldalról az adatkonzisztencia kikényszerítését, bár nyilván erre is van megoldás).Gyakorlatban is működik a funkcionális paradigma? Nagy visszhangja c#-ban eddig valahogyan nincsen.
-
joysefke
veterán
válasz
ReSeTer #9827 üzenetére
Bontsuk kétfelé a kérdést. Vagy amit megértettem belőle:
1,
Akarsz valami UI-t csinálni, ami user inputra reagál, csinál valamit és visszajelzést ad.
Nem tudod hogyan kéne a UI-t létrehozni, strukrurálni, úgy hogy aztán később "egy másik metódustból" hozzáférj adott UI elemekhez?
UI-hoz nem szólok hozzá.2,
Van egy fő végrehajtási szálad és nem tudod hogyan kéne egy "jól definiált feladatot" nem a fő szálon végrehatjani hanem onnan a háttérbe delegálni úgy hogy a háttérben az megtörténjen, mellékhatásokat tudjon létrehozni, pld üzenetet tudjon küldeni vagy mondjuk meglegyen a visszatérési értéke?A "jól definiált feladatodat" ki kell szervezned. Legegyszerűbben egy metódusba amire aztán hivatkozni tudsz.
void Something(p1, p2, ..) { .. }
aztán ezt ahelyett hogy a fő szálon meghívnád ezt a Something(..)-et, delegálod a végrehajtását a threadpoolnak. Ezt a Task.Run(..) nal teszed meg és paraméterként átadsz egy delegate-et amelyik hivatkozik a metódusodra.
Tehát a fő szálon ahonnnan delegálsz :
p1 = ...;
p2 = ...;
var t = Task.Run(() => Something(p1, p2, ..))
// fő szál nincsen blokkolva, a 't' visszatérési érték referencia a Task objektumra amibe a delegált feladatod csomagolva lett.Ebben a példában a "Something" egy visszatérési érték nélküli metódus, tehát mellékhatásokkal operál.
Ha azt szeretnéd, hogy egy másik kódrészlet értesítést kapjon a "Something"-ben történtekről, pld hogy az éppen hol tart, akkor ezt a Something-nek átadott paramétereken kerszül tudod legegyszerűbben megtenni. Paraméterként átadsz egy delegate-et amit a "Something" fel tud hívni mintegy üzenve a külvilágnak.
pld átadsz neki egy Progress<T>-t paraméterként ezen keresztül pedig a Something vissza tud jelezni a Progress<T> gazdájának. (A Progress<T> egy Action<T> delegatet csomagol be, UI kompatibilis módon.)
Something(p1, p2, .., IProgress<int> progress)
{
progress.Report(0);Thread.Sleep(1000) // CPU work
progress.Report(50);Thread.Sleep(1000) // CPU work
progress.Report(100);
} -
joysefke
veterán
Próbált már valaki C# projektet funkcionális paradigma szerint fejleszteni? Működőképes koncepció lehet ez jelenleg egy valós jól szeparált projekt esetében?
Amennyire utánaolvastam ez https://www.nuget.org/packages/LanguageExt.Core/ az egyik jelentősebb funkcioális osztálykönyvtár kiegészítés C#-hoz. És csak 5m letöltés. Ahhoz képest, hogy a nyelv egyre inkább a funkcionális irányba fejlődik az újabb verziókkal, nem tűnik jelentősnek az érdeklődés.
A témával foglalkozó könyven amit éppen olvasok a hibakezelés nagyon tetszik.
-
joysefke
veterán
válasz
leslie23 #9798 üzenetére
Alternatív megoldásként felmerült, hogy a parallel végrehajtásnál csak egy DataSetben tárolnám a lekérdezések eredményeit, majd ezt követően egy külön műveletben sorosan generálnám le az Excel-riportokat.
Igen, érdemes kódban is elkülöníteni az egymástól nagyon különböző feladatok megvalósítását. Ezzel a hibák kezelését könnyíteni tudod.
Fogod a Parallel.Forech-edet és ahelyett hogy az abban levő kód (delegate) csinálja a az SQL lekérdezést ÉS az Excel interop hívását:
A Parallel.Foreach csinálja csak
-1. az SQL lekérdezést /ahogyan eddig/, az adatok esetleges modellekbe való transzformálását,
-2. majd az eredmények összefésülését. <= ennek thread safnek kell lennie.A 2.-höz használhatsz BlockingCollection<T>-t ami thread safe. A ForEach által futtatott kód az SQL lekérdezés eredményét kiszedi a readerből, opcionálisan áttranszformálja valami modellbe (ez a "T") majd ezt beszúrja a BlockingCollection<T>-be.
A Parallel.Foreach futása után egyetlen szálon végigiterálsz a A BlockingCollection-ön és feldolgozod a kinyert és összefésült adatokat => meghívod egyenként az Excel interopodat minden egyes adatelemre.
-
joysefke
veterán
Kicsit off.
Szeretném megkérdezni, hogy ki használ tabletet Pluralsight videók nézésére, illetve szakmai könyvek olvasására?
Szeretném tudni, hogy mi a minimum méret, felbontás, ahol már olvashatóak a ps videón a betűk illetve a könyvek. -
joysefke
veterán
válasz
ReSeTer #9783 üzenetére
Erre azt írják, hogy rekurzívan (mélyen) klónoz:
OpenXmlElement.Clone Method (DocumentFormat.OpenXml) | Microsoft Docs -
joysefke
veterán
Van egy basic classem, kb 10 környéki color propertyvel, nevezzük ezt Light-nak.
A "basic class" megnevezés base class helyett elég rendesen zavarja a megértést.
Öröklődés helyett miért nem definiálsz valami "color profile"-okat leíró egyszerű osztályt, pld "ColorProfile", annak lehetne 1-2 static readonly beégetett értéke, pld ColorProfile.Light, ColorProfile.Dark, de nyilván lehetőség lehet akár custom példány létrehozására is (pld egy ColorProfile.Default-ból) ha van erre igény.
Annak eldöntését hogy éppen milyen ColorProfile van érvényben azt egy másik osztály (-nak példánya) végezhetné ami kérésre előrántja konfigurációból vagy akárhonnan.
Mondom ezt egy sör után, illetve anélkül, hogy tudnám, hogy milyen frameworkben mit csinálsz, illetve UI-ban nem vagyok otthon
Öröklődést akkor van értelme használni amikor egy osztály viselkedését akarod módosítani/definiálni és nem akkor amikor egy egyszerű property értékét le akarod cserélni.
-
joysefke
veterán
válasz
martonx #9772 üzenetére
Kérdése alapján már a táblákban kódolva van a struktúra (ki-kinek gyermeke) ezt kéne dekódolni és meghatározni, hogy a gráf csúcsai hogyan nézzenek ki kódba öntve, illetve hogyan tárolják a köztük lévő relációkat.
A kérdés nekem arra utal, hogy nem tudja, hogy a "normál" tömbökön túl van még dinamikusan bővíthető tömb, több dimentiós tömb illetve más ravaszabb struktúrák. Tapogatózik, hogy hogyan lehetne sok relációt flexibilisen tárolni, felépíteni.
Sokimm
Én azzal kezdeném, hogy
-(1)
körbenéznék, hogy milyen az általad használt UI-keretrendszerben támogatott gráf-megjelenító komponens van és melyiket szeretnéd viszont látni.-(2)
Megnézném, hogy annak mi a publikus interfésze, milyen formában várja a gráfot. Valószínűleg előírja a csúcsok és esetleg élek osztály-formátumát. Neked ehhez kell alkalmazkodni, ebben a struktúrában kell felépítened az adatbázis alapján a gráfot. Feltéve, ha nem akarsz saját UI- komponenst gyárani-(3)
Megnézném, hogy az adatbázis által kódolt gráf-csúcs szomszédossági információt hogyan tudom dekódolni és ebből előállítani azt a runtime-struktúrát ami a UI-komponensnek kell.Minnél közelebb van az adatbázis által kódolt struktúra ahhoz ahogyan a UI komponens várja annál inkább jobb pozícióban vagy. Minnél távolabb, annál rosszabb.
-(4)
Lehet hogy kell egy C# és/vagy gráfalgoritmus gyorstalpaló. Kérdésed alapján csak az egydimenziós tömböket ismered. Jó lesz ha képbe kerülsz a List<>, Queue<>, Stack<>, Dictionary<,>, HashSet<>, LinkedList<> típusokkal C# oldalon, ha csinálni is kell valamit a gráfokkal. Ugyanez vonatkozik a gráfalgoritmusokra. Feljebb volt is egy olvasós link #9770. -
joysefke
veterán
válasz
ReSeTer #9761 üzenetére
Azt az excel-t nem én irányítom, de ha változik is valami, általában csak annyi, hogy arrébb megy néhány oszlop, mert beszúrnak egyet, vagy törölnek egyet. Ez van.
Az excel a programod publikus API-ja. Ha a másik fél nem tartja magát hozzá, akkor a te programod sem tud stabilan működni. Ha a másik fél valamiért nem tudja magát fixen (legalább verziószerűen) az API-hoz tartani, akkor koncepcionálisan rosszul van kidolgozva az az API. -
joysefke
veterán
válasz
ReSeTer #9754 üzenetére
Miért nincsen védve az excel vagy annak bizonyos részei a nem kívánt változtatásokkal szemben? Minden lapot/cellát védeni kéne ami az appnak bemenetéül szolgál.
Ha a programod függ a konkrét excel dokumentumtól, akkor ha képtelen vagy elérni azt, hogy ne barmolják szét a bemenetül szolgáló excelt, akkor azt is képtelen leszel elérni, hogy aki "szétbarmolja", az majd pontosan vezesse, hogy mit "barmolt" szét...
szerintem...
-
joysefke
veterán
Roslyn-nal sikerült működésre bírnom a dolgot, (kb end-to-end megy fordítástól, az authentikációig és sikeres API hívásig
)
De a fordítás csak úgy működik, ha CSharpScript-et használok, ez az opció ahogy látom impliciten felhasználja a runtime betöltött assembliket referenciaként a fordításhoz /ami nincs betöltve csak azt kell referálni/.
CSharpCompilation-nal ugyanaz a fordítás nem működik. Itt nekem kéne expliciten megadni az assembly referencákat, amit természetesen hiánytalanul meg is tesztek. Aztán kapok egy undorító, Google által jól ismert fordítási hibát ami arra panaszkodik hogy a System.Net.Http.dll verzió mismatch van, az assembly ahonnal dinamikusan fordítom a kódot (és ahová interfész miatt függősége van a fordított kódnak) 4.2.0.0-t val lett fordítva, a Roslyn pedig 4.0.0.0-t akarna használni. Hogy a 4.2.0.0 honnan jött, azt nem tudom, de kézzel nem tudom betölteni. Hogy CSharpScript-tel ez miért és hogyan működik azt persze nem tudom.
Majdnem biztos vagyok benne, hogy a hibának semmi köze nincsen a Roslynhoz magához vagy akár a kódomhoz, egyszerűen nem azt a verziót kapom DLL-ből amit szeretnék.
Akik nálam jobban értenek a fordításhoz biztos meg tudnák oldani, meg lesz ez nálam is oldva, hogy "CSharpCompilation"-nel is működjön, de ez így egyáltalán nem bizalomgerjesztő...
Félek, hogy ami az én gépemen dinamikusan fordul, produktív gépen majd esetleg nem fog. Egy halom DLL-t pedig nyilván nem akarok betenni a repoba és nuget helyett azokat referálgatni vagy hasonló okosság.
===
Szóval most a pluginok kerültek fel az asztalra:
Talán ahelyett, hogy konfigból (encryptált DB-ből) on the fly fordítjuk a konkrét megvalósítás kódját, jobb ötlet lenne szükség esetén egy újabb plugin-dll-t berakni egy plugin könyvtárba aztán onnan betölteni a konkrét megvalósítást.Ilyen önműködő plugin megvalósításhoz van net 472-re ennél jobb cucc?
Managed Extensibility Framework (MEF) - .NET Framework | Microsoft DocsHasználta ezt már valaki?
-
joysefke
veterán
Eddig csak az első linket néztem meg (azt is egyelőre csak NET6-tal), de szerintem nekem pontosan erre (Roslynra) lesz szükségem.
Valamiért az volt bennem, hogy csak modern platformra van, ezért nem is néztem utána. Az "Add-Type" valami régi fordítót használ, régi C# verió támogatással és a hibaüzenetei borzalmasak.
Aztán hajrá a C# szintaktikájú saját DSL létrehozásához.
Annál azért egyszerűbbnek 'tűnik':
Http szolgáltatás daemon-kliens oldalára szeretnék a kliens HttpMessageHandler pipelinejába beépülő nem-interaktív autentikációs komponsenst (pld OAuth2 Client credentials flow) ami a lehető legszabadabban konfigurálható.A szabad konfigurálhatóság biztosítaná, hogy az autentikáció pontosan úgy történjen, ahogy az autentikációs végpont (token url) diktálja illetve a Http üzenetbe a token -vagy ami az autentikáció meglétét jelképezi -abban a formában kerüljön bele, ahogyan a szerver oldal szeretné.
Az tűnik a kiindulási állapotnak, hogy a jövőben több féle (standardtől kicsit eltérő) lehetőség lesz, mintsem hogy azt statikus konfigurációval le tudjuk fedni.
J.
-
joysefke
veterán
Konfigurációs adatként szeretnék viselkedést definiálni az applikáció számára.
Az éppen járt megközelítés, hogy a konfigurációs adat némi forráskód lenne, amit szükség esetén futási időben fordít az applikáció és a továbbiakban a fordítás eredményét használja fel mint konkrét implementáció.
.Net 472 illetve PowerShell 5.1 áll rendelkezésre, ennél újabb nem. Az
Add-Type -ReferencedAssemblies $assemblies -TypeDefinition $sourceCode
commandlettel szemezek. Ez fordít C#-ot, az elkészülő Type -ot pedig az applikáció fel tudja használni.Találkozott valaki ezzel a feladattal? Van az adott platform-verzióra ennél jobb ötlet, kiszámíthatóbb, modernebb compiler dobozból? Van az "Add-Type"-pal tapasztalat? Alkalmanként egyetlen osztályt akarok fordítani, de az nem feltétlenül "Hello world"...
-
joysefke
veterán
válasz
joysefke #9711 üzenetére
lemaradt:
Mivel DI-t és teszteket szeretnél használni (hogy az egész 1b arch egyáltalán értelmet nyerjen) ezért valahol össze kell állítanod a DI konténert (ez a composition root, a te esetedben a ConfigureServices metódus az ASP templétben).Magának az ASP projektnek értelemszerűen nem kéne sőtt nem szabadna dependenciája legyen mondjuk az Ef projekthez, de a composition rootnak (ConfigureServices metódusnak) szüksége van rá, mivel ez alapvetően a solutionben lévő összes függőséget referálja. Ez ezen az egy ponton rendben van. Ha zavar, akkor a DI-konténer összerakását kiszervezheted egy másik csproj-ba.
-
joysefke
veterán
válasz
leslie23 #9709 üzenetére
Két párhozamos dologról volt szó amelyek egymástól valamennyire függetlenek:
A fontosabb döntés:
1,
1a, N layer (Te nyilván háromban gondolkodsz) vs 1b Hexagonal (vagy ahogyan hívni szeretnéd) arch.másodjára
2,
2a, Generikus Repo/UoW mögé rejtett EF DbContext vs 2b Domain specifikus perzisztencia interfészek (nem tudom a nevüket bocsi)Én azt sugalltam, hogy ne próbálj meg tankönyvi N-layert csinálni.
Ezen felül nekem fenntartásaim vannak azzal kapcsolatban, hogy az DbContext-et bezárjuk egy generikus Repo/UoW mögé és majd az "applikációs réteg" használja a az Insert/Update/ etc metódusokat (az eredeti írásodból azt olvastam ki, hogy erre készülsz) .
Szóval anélkül, hogy tudnám, hogy egyáltalán mit akarsz csinálni, nekem az alap hozzáállásom egy újabb kis hobbiprojektemhez amiben van ASP meg DB a következő lenne (a nevek szabadon variálhatóak, csak próbáltam beszédes neveket varázsolni):
MyProjekt.ASP => MyProjekt.Core <= MyProjekt.Ef
Nincsenek rétegek és nincsen sem teteje sem alja, viszont van közepe meg vannak a többiek. A nyilak a dependencia irányokat mutatják.
Mindenki a közepét referálja, a közepe viszont nem referál olyan dolgokat amelyektől nem akar függeni. Nem referálja sem a saját EF vagy ASP függő projektjeidet sem magát az ASP vagy EF frameworkot
Amikor a közepe valamit akar a "széllétől", akkor azt egy saját magában definiált interfészt használva teszi meg
Ennek két hatása van:
-a közepe mindenki nélkül, önmagában is fordul, ez megteremti a lehetőségét, hogy könnyedén unit teszteld
-a közepe a függőségeket (pld EfPerzisztencia) DI formájában (leginkább konstruktoron keresztül) kapja meg, ez pedig megint erősíti a közepének a unit tesztelhetőségétAhhoz, hogy ez megvalósuljon, a dependenciák invertálva vannak:
Ha ez egy N-layer arch lenne, akkor az "Application layer" referálná a DAL-t (vagy közvetlenül, vagy interfészen keresztül, de az interfész is logikailag a DAL-ban lenne).
De itt nem, itt ez fordítva van. Itt amit a DAL (ábrán MyProject.Ef)-tól a Core használni akar, az interfész formájában definiálva van, és ez az interfész a "Core" része és a DAL valósítja meg.Másrészt a "Core"-ban lévő dolgoknak amelyek valamit akarnak a széllétől (pld perzisztálni) nyilván szükségük van olyan objektumokra amelyek ez meg is tudják csinálni (megvalósítják azt az interfészt amit a "Core" adott osztálya éppen használni akar). Ezek az objektumok DI-jal kerülnek be leginkább mint konstruktor paraméter. A DI konténert a te esetedben az ASP-s template ConfigureServices-ban tudod konfigurálni (ez gyak. az applikáció belépési pontjánál van).
Visszatérve a konkrét kérdéseidhez:
-Az ASP-s Controllerek, View-k Modell-ek (azok amelyek a Html-be szállítják az adatot) azok mind az ASP-s projektedbe kerülnek.-A Core-ba kerül minden "domain model" (első körben az entitásaid is mindenképpen akár van annotáció rajtuk akár nincs) meg mindenféle logika ami ezeket érinti.
-A "Core"-ból mindenféle frameworkos stabil osztály felé mehet dependencia, pld a DataAnnotation-t amit korábban felvetettél reálisan nem fog problémát okozni és a tesztelést sem nehezíti meg.
-Mehet külső dolgok irányába is, ha azok nem nehezítik a tesztelést meg nem akarod őket soha lecserélni. pld Newtonsoft.Json.
-A "Core" specifikálja interfészekkel, hogy mit kell tudjon a perzisztencia (meg egyéb függőségek amelyektől akar valamit) és ezek az interfészek a core-ban vannak.
-A külső projektekben lévő függőségek pedig megvalósítják a Core-ban azt/azokat az interfészeket amelyek miatt nekik egyáltalán helyük van a szolutionben.
Tehát ha maradsz a generikus repositorinál, "2a" akkor a Te általad tervezett ...
IPersonRepository
,IProductRepository
, ...IRepository<T>
...IProductRepository
...IRepository<Product>
interfészeid is mind a "Core" ba mennek,egy a lényeg, a Core-ba nem kerülhet be EF függőség (tehát az interfészeid metódusainaknak sem lehet EF ben deklarált paramétere, visszatérési értéke). A Repository interfészed konkért megvalósítása viszont az Ef-projektbe kerül.
Vagy dobod a generikus repository-t ez a "2b" és ekkor a Core-ban nem a fenti teljesen álltalános perzisztencia interfészek lesznek mint hogy az IPersonRepository-n lesz mondjuk egy void Save(Person person), hanem lesz mondjuk egy (csak a példa kedvéért)
IPersonCommands
{
void SetProfileImage(int personId, Picture picture);
}
ugyanúgy a "Core"-ban, ezt meg mondjuk megvalósítja egy EfPersonCommands az Ef projektben. Szintén csak a példa kedvéért:EfPersonCommands: IPersonCommands
{
IDbContextFactory<PersonContext> _factory
// vagy Optionst injektálsz (az a preferált ebből szintén elő tudsz állítani Contextet amikor kell) vagy factoryt, mindkét opció tiszta lesz DI-jal,
EfPersonCommands(IDbContextFactory<PersonContext> factory)
{
_factory = factory // throw if null..
}
void SetProfileImage(int personId, Picture picture)
{
using var context = _factory.Create();
//csinálsz valamit
context.Save() <= tranzakció
} <= dbcontext dispose
}
A kliens pontosan azt kapja amire szüksége van (cserébe potenciálisan több metódusod lesz), a megvalósításba már bele van csomagolva a tranzakció.
2a vs 2b az részletkérdés (könnyen tudsz változtatni bármelyik irányban), 1a vs 1b viszont egyáltalán nem. -
joysefke
veterán
válasz
Alexios #9707 üzenetére
Nekem ezzel és ehhez hasonló generikus repositorikkal: Implementing the Repository and Unit of Work Patterns in an ASP.NET MVC Application (9 of 10) | Microsoft Docs
Az a bajom, hogy az ilyen metódusok mint Update<T>(T entity) , esetleg Save<T> (vagy Upsert<T>), Delete() elhitetik a hívó oldalon, hogy ennyire egyszerű a perzisztencia, hogy meghívod őket utána a UoW-ön egy Save()-t és kész. És hogy ez mindenre működik amit típus paraméterként át tudnak adni.
Holott
-nem feltétlenül értelmezhető/működik minden lehetséges T entitás típuson az összes művelet,
-nem hívhatsz egymástól függetlenül mindenféle Repository metódust egy UoW tranzakción belül,
-illetve lehet hogy mondjuk az Update<T>(T entity) működik, de mondjuk az adott konkrét entitásra nem a mindenkire érvényes implementáció-t akarná a kliens kód hajtani.
-Az is lehet hogy van egy entitásod ami már trackelve van, mivel az egyik repository metódus impliciten előkerítette, majd a másik ráhív egy attach-ot a már trackelt entitásra. => exception, holott amit a kliens el akar érni annak van értelme és meg is valósítható lenne egy tranzakción belül (DB engedné egy megfelelő SP-vel, illetve engedné az EF is, ha ügyesen lenne megcsinálva).Ami nekem sokkal szimpatikusabb:
Kliens kód kap egy interfészt amin azok a perzisztencia műveletek vannak amelyekre a kliensnek konkrétan szüksége van.
Az interfészt megvalósító osztály EF-függő, az adott metódusa pedig közvetlenül indít EF dbcontext-et (lehetőleg DI-on keresztül szerez ehhez egy DbContextFactoryt vagy azzal egyenértékű opciót amiből Contextet lehet előállítani), közvetlenül attach-csolhat entitást és állít EntityState-t, illetve menti a tranzakciót. Tehát kihasználja az EF tényleges tudását és azt biztosítja a hívónak amire annak szüksége van, lehetőleg egyetlen hívásból.
-
joysefke
veterán
válasz
leslie23 #9705 üzenetére
Én sem vagyok guru
N-tier architecture-t próbálok kialakítani
tankönyvekben jól működik....van egy DataAccess, amibe a Repository és UnitOfWork pattern dolgai és az EF Core-specifikus dolgok kerülnek...
Az én személyes nem feltétlenül objektív véleményem erről az EF+UoW/Repository a témáról.
Az Ef DbContext osztálya az már önmagában egy UnitOfWork, benne a DbSet<T> pedig egy Repository megvalósítás.
1,
Ezt becsomagolni egy másik UoW/Repository abszrakcióba csupán azért hogy legyen egy repositorid vagy UoW-öd önmagában semmi értelme.2,
Ha azért csomagolnád be a DbContext-et egy abszrakt, generikus UoW / Repository petternbe, hogy az EFCore egy absztrakció mögé kerüljön, és a felsőbb réteg ne dependáljon közvetlenül az EF felé, akkor ez nemes és jó indok, de saját tapasztalatom alapján nem működik jól.Itt van pld a docs.microsoft.com oldalán egy Generikus Repository UoW sablon ami absztrakció mögé helyezi a Repo/UoW pattern konkrét megvalósítását, az EfCore DbContext-et: Implementing the Repository and Unit of Work Patterns in an ASP.NET MVC Application (9 of 10) | Microsoft Docs
Nekem ezt az absztrakciót mentésre (C/U) a legprimitívebb esetektől eltekintve nem sikerült érdemben használni. Orrán száján ereszt. A relációs adatbázis FK constraintjei illetve hogy az EF change tracker éppen melyik rigojáját alkalmazza fogják meghatározni, hogy egy Update az éppen működik vagy sem. Az relációs constrainttel nincs gondom, de a másik az nekem komoly probléma.
...Jelenleg a Data projectben van egy ViewModels mappám, de logikailag ezeknek lehet a Presentation layerben lenne inkább a helye....
N-layerben az egyes layerek csak lefele dependálnak és ha egy mód van rá, akkor csupán a közvetlenül alattuk levő réteg felé. A ViewModel az prezentációs réteg (az ASP-kontrollerrel együtt).
...tetszik, hogy így a Data layerben nincs data annotation használat (Required és ErrorMessage stb.), hiszen ezek a dolgok logikailag gondolom inkább a Presentation layerhez tartoznak...
Optikailag nem néz ki jól, ha egy több projekt által használt model osztályon olyan speciális attributumok vannak definiálva aminek semmi köze az adott assembly céljához, DE a Te esetedben a "System.ComponentModel.DataAnnotations" az ugye része a Core frameworknek és része lesz a jövőben is és a visszafele kompatibilitás adott lesz. Ezért ez egy "nem-volátilis dependencia", reálisan soha nem lesz útban, soha nem romlik el, max a szemedet fogja szúrni. Szemben mondjuk az EF Core-ral, ami egy "volátilis dependencia": 1-2 évente újraírják és minden verzióugrás tele van funkció-törő változtatással.
Ráadásul ugye a "System.ComponentModel.DataAnnotations" használata vagy nem használata semennyiben nem fogja a tesztelhetőséget befolyásolni, míg a DAL tesztelése vagy tesztekben való kiváltása az egy téma amivel majd foglalkozni kell, szóval a DataAnnotations elhelyezése -szerintem- az utolsó prioritás amin töprengened kell.
szükségem van ... mappingre, ami manuálisan nyilván sok-sok favágó kód írásával járna, AutoMapperről pedig azt olvasom, hogy nem igazán jó megoldás, ha oda-vissza adatátadás történik.
Én is csak ezeket ismerem. Hogy két irányú mappelésnél mi lenne a probléma, azt nem tudom. N-layer esetén mivel a felső réteg ismeri/hívja az alsót, ezért logikusan a felsőbb rétegnek kell hívnia a mappelést is. (mivel az alsóbb réteg nem ismeri a felsőbb rétegben definiált modellt (fordítva viszont igen), hiszen nincsen oda dependenciája (projekt referálása)). A mappelés az logikailag infrastruktúra kód "plumbing". Minden réteg használhatja (dependálhat felé), ennek megfelelően be lesz betonozva a projektbe.
Egyáltalán helyes a megközelítésem? Köszi előre is!
Ha maradsz az N-layernél, akkor az, hogy minden réteg (ami nem valamilyen mindent átható infrastruktúra (mapper/logging)) az csak lefelé dependál. Ha az EF-Core-DAL-t reálisan ki akarod váltani vagy szeretnéd, ha egy EF Core 6 DAL => EF Core 7 DAL váltás sima legyen, akkor lehet hogy jó ötlet lenne az applikációs logikát a DAL-tól egy DAL interfész segítségével elválasztani, ami a saját önnálló assembly-jében van. Ez a stairway pattern. A DAL megvalósítás interfészen keresztül (amely külön assemblyben van) le van választva a használójától és a megvalósításától is. Ennek van egy pozitív hozadéka: Le tudod fordítani a solutiont működő DAL megvalósítás nélkül is. => És ez visszafele is igaz. Enélkül ha nem fordul a DAL projekt, akkor semmi sem fordul.Ahogy én állnék neki (és ez szubjektív és nem feltétlenül helyes megközelítés):
Dobnám az N-layert publikus generikus repositorival meg UoW-kel együtt.Lenne egy prezentációs projekted (ASP), lenne egy külön konkrét EF-Data access megvalósítás projekted meg lenne egy olyan projekted ami sem a prezentációs sem a data access projektet nem referálja. Ez tartalmazná az entitások modell osztályát is , illetve az összes interfészt amelyeken keresztül mondjuk a perzisztenciát akarja vezérelni. Az interfész pontosan azt és csak azt deklarálná amire a központi projektednek szüksége van. Meg tartalmazná az összes tiszta domain-logika kódot. A lényeg, hogy ez a központi projekted kifelé nem dependálhat volátilis dependenciák (EF Core, Adatbázis) irányába. Dependenciák invertálva vannak befelé.
A cél itt az, hogy volatilis dependenciák hiányában a központi projekted könnyedén unit tesztelhető legyen. Az emlegetett mappelgetés is sokkal kisebb probléma.Üdv
J. -
joysefke
veterán
válasz
ReSeTer #9695 üzenetére
A kód esetleg futhatna központi helyen, egy belső webszerveren, intranet oldalon?
-(1) felhasználó az oldalra navigál,
-(2) letölti az általad publikált "mester" excel templatet -ezáltal rá tudod kényszeríteni mindig a legfrissebb sablon használatára-. Mert nyilván a sablon is változni fog.
-(3) kitölti, feltölti egy formmal
-(4) szerver oldali kód az excel alapján valami wordot generál, azt letölti a felhasználóHa nem tartod kézben a környezetet és hogy mindig mindenki legfrissebb sablont használja, akkor az nagy kényelmetlenség lehet.
(ilyet officeos dolgot még nem csináltam lehet elkerülte valami a figyelmemet) -
joysefke
veterán
válasz
ReSeTer #9686 üzenetére
A végfelhasználónak meg egyéb személyeknek semmi köze a koncepcióhoz.
Néhány ezer sor fölött már fontos tényező, hogy a bonyolúltságot elrejtsd / leválaszd egy megfelelő osztályba/komponensbe és annak felhasználási pontján már csak néhány egyszerűen használható tiszta interfészt látszódjon.
Ez akkor is igaz, ha te írod az egész szoftvert.
Különben hamar spagettivé válik az egész. Ha többen fejlesztik a kódot, akkor ez fokozottan érvényes. Ha fel kell használnod egy létező , működő komponenst, akkor jó esetben elég megnézned a publikus interfészeit és jó eséllyel rájössz hogyan kell használni, felhívni.
Ha minden publikus lenne, akkor az egész kódot át kéne nézni ahhoz hogy használni tudd. -
joysefke
veterán
válasz
ReSeTer #9681 üzenetére
"aki hozzá akar férni" Ennek a korrekt megnevezése az "Client" vagy "Client code" és semmi köze sincsen a végfelhasználóhoz vagy bármilyen személyhez. Magyarul azt jelenti, hogy a hívó fél, a hívó oldal.
Ha deklarálsz egy interfészt vagy egy( publikus osztályon egy) publikus metódust, konstruktort akkor az kívülről látható lesz, tehát lesz olyan kód, ami látja a publikus metódust és fel akarja hívni. Ebben a relációban a publikus metódust hívó kód a "Client" és ami belül van (számára láthatatlan) az az implementációs részlet.
Amikor Te felhívod a System.Console.WriteLine(...)-t, akkor abban a relációban a Te kódod (vagyis nem te hanem a Te kódod) a kliens. Belül meg lehet hogy hegyek mozognak, Te pedig csak annyit látsz, hogy megjelenik a szöveg a konzolon, vagy ahová a kimenet mutat.
..Egy user általában felületen keresztül vezérli a programot...
A koncepciónak tökéletesen semmi köze nincsen a végfelhasználóhoz.A hívó kód - hívott kód koncepció minden szinten értelmezhető. Minden egyes fgv-hívásnál van egy hívó fél és van egy hívott fél. (tehát assembly-n belül is értelmezhető)
Röviden az implementiációs részletek elrejtésére szolgál a dolog. A hívó félnek minnél kevesebb dologgal kelljen törödnie ahhoz, hogy igénybe tudja venni egy publikus interfész/metódus által nyújtott "szolgáltatásokat".
A bővebben érdekel, akkor erről könyveket írtak.
Pld ezt tudom ajánlani:
Amazon.com: Adaptive Code: Agile coding with design patterns and SOLID principles (Developer Best Practices) eBook : McLean Hall, Gary, Hall, Gary McLean: Kindle Store -
joysefke
veterán
json-ba szerializálod az adatokat majd azt kiírod. Ha nincs sok adat, akkor szerializálod az egész listát és kiírod. Ha sok az adat akkor steamelni illene (meg nem txt fájlokat használni)
Serialize an Object (newtonsoft.com)Új projektnél az újabb (egyelőre kicsit butácskább) System.Text.Json -t használnám a fenti helyett, de a fenti is tökéletesen jó lesz.
-
joysefke
veterán
-
joysefke
veterán
Nem teljesen értem a feltételt. Arra van szükséged, hogy visszakapd:
A, azon dictionary-k felsorolását, amelyek rendelkeznek egy bizonoys kulccsal, VAGY
B, azon dictionary-k felsorolását, amelyek rendelkeznek egy bizonoys kulccsal amelyhez adott érték tartozik?List<Dictionary<string, string>> nagy
;A, // ahol van "xx" kulcs
nagy.Where(a => a.ContainsKey("xx"));
B, // ahol van xx kulcs és az ehhez tartozó érték "yy"
nagy.Where(a => a.TryGetValue("xx", out string val) && val == "yy");
a végén hívhatsz egy ToList()-et
-
joysefke
veterán
válasz
pvt.peter #9576 üzenetére
Szinte biztos, hogy nem atomi, mint ahogyan az "i++" sem atomi, hiába fér bele egy sorba. Az if operatoros verzió amit helyettesíteni akarsz pedig garantáltan nem atomi.
Kérdés, hogy miért van szükséged atomi műveletekre? Az atomi műveleteket biztosító C# osztályt egyébként itt találod: Interlocked Class (System.Threading) | Microsoft Docs
Miért nem használasz egy "shared nothing" megközelítést ahol az adott konkurens metódusaid semmilyen közösen használt változót/adatot nem használnak? Vagy miért nem lockolsz valamilyen szemafor konstrukcióval a kritkus kódon (kritkus kód == írás művelet bármilyen közös változón)
SZERK
ezt dobta a kereső:
What are Atomic operations and what are not?
In C# Specification, the stamement about atomic operation is:
“Reads and writes of the following data types shall be atomic: bool, char, byte, sbyte, short, ushort, uint, int, float, and reference types.” Also: “…there is no guarantee of atomic read-modify-write, such as in the case of increment or decrement.”.
a ??= operator szerintem a read-modify-write kategóriába esik... -
joysefke
veterán
Már lassan én is elvesztem a fonalat...
Egyrészt nem értem ezt az ide-oda tilitolit, az egyikben ez benne van, a másikban meg valami más. Tudom, én vagyok megrögzött, régimódi, de én ha valami jól működik, azon nem változtatok (tehát én ezt a frameworkök közti váltást teljesen visszafelé kompatibilis módon oldottam volna meg).
Pedig annyira nem bonyolúlt a dolog, és lehet lenne értelme utánanézni, ha már egyébként is foglalkoztat.Semmilyen tili-toli nincsen. Mióta a .Net Core (igen, a NET 5 is ide tartozik) vonal megjelent ezt rohamléptekben fejlesztik, az előző .Net Framework vonalat pedig csak minimális mértékben csiszolgatják.
A Core vonal már eleve multiplatformnak lett tervezve, illetve a fejlesztési modell is más. A távlati cél, hogy ez nem csak szebb jobb, gyorsabb és multi platform lesz, hanem hogy a Net 4.X szinte minden támogatott funkcióját -aminek értelme van- továbbvigyék. Ez utóbbi nagy feladat ezért csak inkrementálisan lehetséges.
-
joysefke
veterán
Dictionary<string, object> -be deszerializálni nem megoldás?
Ez tartalmazná az első hiearchia propertijeit azok neveivel mint kulcsokkal és a hozzájuk tartozó "nem túl típusos" objektumértékkekkel. Ami kulcs hiányzik, olyan property nem volt a Jsonban.
Ha a második hiearchiaszint propertijei már erősen típusosak, akkor ott _gondolom_ már működni fog a castolás object-ről?
Ha a dynamic vonalon indulsz el, nézd meg az ExpandoObject-et. Ez is egy <string, object> dictionary valosít meg, többek között.
-
joysefke
veterán
válasz
pmonitor #9470 üzenetére
1,
bent maradt a hot pathban a Console.WriteLine() ==> így nem lehet tesztelni. Ha kiveszed sokszorosára gyorsul majd. (csak akkor ugye hol lesz az eredmény)
2,
Nem készítesz a bemeneti tömbről másolatot (ami nem feltétlenül baj) de ez azt jelenti hogy a bemeneti tömböt az első futás első iterációja elött egy rendezéssel már tönkreteszed. az algo aztán folyamatosan pörgeti a tömböt míg annak a rendezése át nem fordul (növekvőről csökkenőre)Kizárólag az algoritmus felépítésének köszönheted (és nem a benchmark felépítésének) hogy a tömb amin dolgozol hiába teszed tönkre az algo minden futásával újrarendeződik és így minden futás az első kivételével pontosan ugyanannyi lépést jelent. Az elsőben a qsort ideje különbözni fog a többi futás qsortjának idejétől (de ez elhamyagolható)
-
joysefke
veterán
válasz
pmonitor #9466 üzenetére
Átírva C#-ba és használható formában
A kezdeti 1x tömb-klónozáson kívül (hogy ne legyen elrontva a bemeneti tömb) teljesen allokációmentes.
A char[] State tárolja az aktuális állapotot, a bool Next() pedig lépteti az és visszajelez a sikerről. Ha a char[] State állapotot nem csak olvasni akarod akkor értelemszerűen ki kell menteni róla egy másolatot.A char[] State köré lehetne még valami readonly wrappert rakni, de azt nem tudom hogy viselkedne.
char[] megy bele ctor bemeneti paraméterként
És ezen még lehetne gyorsítani.
using System;
namespace Permutator
{
class Program
{
static void Main(string[] args)
{
int i = 0;
var p = new Permutator("abcdananana".ToCharArray());
do
{
i++;
Console.WriteLine(new string(p.State));
}
while (p.Next());
Console.WriteLine($"Nr of results: {i}");
}
}
public class Permutator
{
public char[] State { get; }
int _size;
bool isFinished = false;
public Permutator(char[] symbols)
{
if (symbols?.Length > 0)
{
_size = symbols.Length;
State = (char[])symbols.Clone();
Array.Sort(State);
}
else
throw new ArgumentException("input must be non-empty");
}
public bool Next()
{
// if we have already finished we indicate failure on getting next element
// else we try to advance the state and propagate success of advancing state
if (isFinished)
return
false;
isFinished = !AdvanceState();
return !isFinished;
}
bool AdvanceState()
{
// Find the rightmost character
// which is smaller than its next
// character. Let us call it 'first
// char'
int i;
for (i = _size - 2; i >= 0; --i)
if (State[i] < State[i + 1])
break;
// If there is no such character, all
// are sorted in decreasing order,
// means we just printed the last
// permutation and we are done.
if (i == -1)
return false;
// Find the ceil of 'first char'
// in right of first character.
// Ceil of a character is the
// smallest character greater
// than it
int ceilIndex = findCeil(State, State[i], i + 1, _size - 1);
char tmp = State[i];
State[i] = State[ceilIndex];
State[ceilIndex] = tmp;
Array.Sort(State, i + 1, _size - i - 1);
return true;
}
// This function finds the index of the
// smallest character which is greater
// than 'first' and is present in str[l..h]
int findCeil(char[] str, char first, int l, int h)
{
// initialize index of ceiling element
int ceilIndex = l;
// Now iterate through rest of the
// elements and find the smallest
// character greater than 'first'
for (int i = l + 1; i <= h; i++)
if (str[i] > first && str[i] < str[ceilIndex])
ceilIndex = i;
return ceilIndex;
}
}
}
-
joysefke
veterán
válasz
pmonitor #9463 üzenetére
Ha ez a feladat akkor én itt egyetlen tömbfoglalást sem látok:
Print all distinct permutations of a given string with duplicates - GeeksforGeeks -
joysefke
veterán
válasz
pmonitor #9461 üzenetére
De ez az összes többi esetre is vonatkozik(teszt_1-teszt_5-ig). Nem állítom, hogy a teszt atompontos. De többször lefuttattam, és mindig hasonló eredményt adott az egymáshoz viszonyított idők tekintetében.
A teszt mér valamit, de nem azt amire te kiváncsi vagy.
Az optimalizálás 5letét az ismétléses permutáció algoritmusa adta. Ott nagyon sokat kell allokálni és feltölteni(bár a legjobb az lenne, ha csak feltölteni --tehát simán másolni-- kellene).
Ha nem kell a mélységi bejárás során keletkező összes tömböt megtartani, csak mindig 1-1 újabbra van szükséged és tudod hogy egy tömbre mikor nem lesz már szükség, akkor érdemes lehet ezt kipróbálni. Ezzel ki tudod küszöbölni a heap allokációt. Én még nem használtam.
-
joysefke
veterán
válasz
pmonitor #9458 üzenetére
static unsafe void teszt_6(int[] source, int n)
{
int[] dest = new int[n];
fixed (int* pSource = source, pdest = dest)
{
int* pSource_0 = pSource;
int* pdest0 = pdest;
int* pmax = pSource_0 + n;
for (; pSource_0 < pmax; ++pSource_0, ++pdest0)
{
*pdest0 = *pSource_0;
}
}
}
mivel a metódusnak visszatérési értéke nincsen (void), a program végeredménye szempontjából lényeges mellékhatás sincsen (nincsen IO, nem változtat semmilyen állapotot) ezért ezért honnan tudod, hogy futás közben release + optimalizáció beállítással ez egyáltalán lefut? (valószínűleg lefut, de nem kéne)
Ráadásul a timert úgy indítod-állítod le, hogy a memóriamásoláson kívül szinte minden tesztesetedben van ciklikus heap allokáció is. Ha nagyot foglalsz a heapen akkor az triggerelhet egy GC futást is.
Mivel a teszt-metódusaidat ciklusban futtatod, az iterációk között teleszemeteled a heapet halott objektumokkal ezért FOG futni a GC, többször, sokszor. A GC futás valószínűleg több időbe kerül mint maga a memóriamásolás. (pld mert a memóriaterületeket valamikor nullázni is kell stb) . Innentől kezdve a méréseid pontatlanok.
Ha memóriát akarsz kézzel másolni, akkor #9455 szigorúan allokáció nélkül. az kimaxolja a mem sávszélt, az a másolás sebességének elméleti határa
====
Az egészet arra éleztem ki, hogy a "fő programom"(a cutter) esetében sokat kell tömböt másolni. Igaz, hogy csak kis méretűeket.
Csak másolni kell a tartalmat egyik helyről a másikra vagy allokálni kell és feltölteni? Elég jelentős a különbség. (nem ismerem a feladatot)
====
A legnagyobb meglepetést azonban az Unsafe kód okozta. Kis méretű tömb esetén a "középmezőnyben" van. Nagy méretű tömb esetén azonban lényegesen a leggyorsabban végez az összes többinél.
Két oka van:
1,
Az eredeti unsafe teszt-metódusodban nem volt for ciklusos heap allokáció hanem stackalloc volt => nincs GC a szemét eltakarítására, összehasonlíthatatlanul gyorsabb. Az összes többi teszt ahol new int[n] hívódik ciklikusan hatalmas handikeppel indult...
2,
Az unsafe kikapcsolja a tömb hozzáférések során az indexer értéktartomány ellenőrzését. ezzel csökkentetted a ciklusonkénti munkát (indexer értékhatár ellenőrzés + mem másolás helyett csak mem másolás). Gondolom a többi library metódus is unsafe-ként van belül megvalósítva. Csak ugye lsd 1. pont -
joysefke
veterán
válasz
pmonitor #9454 üzenetére
Nem derül ki, hogy mit akarsz csinálni. És mi alapján választottad ki a bementő paramétereket.
static unsafe void teszt_5(int[] source, int n)
{
fixed (int* pSource = source)
{
int* dest = stackalloc int[n];
int* pSource_0 = pSource;
int* pmax = pSource_0 + n;
for (; pSource_0 < pmax; ++pSource_0, ++dest)
{
*dest = *pSource_0;
}
}
}
(1)
bemegy egy tömb és egy int.(2)A stacken foglalsz egy int tömböt
-ami nem tudja elhagyni a stacket
-és nem lehet nagyobb mint a stack mérete (ráadásul a stackből foglalja a helyet aminek a metódus hívásakor már van egy a metódus számára ismeretlen mérete illetve a default stackméret futtatókörnyezettől is függ)(3)aztán feltöltöd az int[n] tömböt és
(4)elfelejtedHa kézzel írnék tömbmásolásra egy UNSAFE metódust akkor bemenetként a már lefoglalt cél és forrástömb referenciáit vinném be aztán SIMD-del 32 byteonként másolnék (AVX register mérete).
Amit te csinálsz ott egy int* pointert inkrementálsz és int méretben történik az adatmozgatás. (a mivel a ciklusok nem függenek az előzőektől ezért jó esetben 3-4 átlapolva történik meg)
SIMD-del egyedül a memória sávszélessége szabna határt
-
joysefke
veterán
válasz
Flashback #9445 üzenetére
Ezt Databindinggal és ObservableCollectionnel szokás megoldani, illetve amikor a user a GUI-n a lista aljára ér, akkor ott keletkezhet egy event amire feliratkozhat a kódod, arra reakcióként pedig betöltheted a következő oldalt (hozzáadod az ObservableCollection-höz, a databinding pedig onnantól elintézi a többit) mondjuk Xamarin.forms-ban ez lenne.
Gondolom oka van hogy nálad így lett megoldva...
-
joysefke
veterán
Nekem is Lenovo volt előtte (Thinkpad T470p szintén 45W procival -4/4 i5-). Ennek 14"-os létére jobb volt a hűtése mint a 15"-os fém és jóval nehezebb Dellnek. A gép egyszerűbb volt, de jobb.
A vállalati Windows alatt azt értem, hogy nálunk egy külön enrollment image van, amit fel kell dobni a gépre.
Nálunk szerencsére nem. Semmi custom vacak nincsen. Szinte minden megy internetről VPN nélkül AzureAD SSO-val. Mint egy álom.
A Windowsban a notepad is többet ér használhatóságban mint ez a noti. egy haszna van: A nagy fényes érintésérzékeny kijelző hétvégén vidéken jól kezelhető fekve az ágyban netezésre filmnézésre.
-
joysefke
veterán
válasz
Flashback #9437 üzenetére
A többiek jól mondják, a ref kulcsszó kell neked, de már a kérdésből gyanús, hogy valamit nem úgy csinálsz ahogy illene:
Ha átadsz egy inicializált List-et paraméterként egy metódusnak, akkor ez esetek nagy részében ezt azért kéne tegyed, hogy a metódus olvassa a List-et, esetleg módosítsa a tartalmát (feltöltse vagy hozzáadjon) és nem azért, hogy a kapott referenciát megváltoztasd és ezáltal az eredeti List adatszerkezetet eldobd. Ha az eredeti List-re nem mutat másik referencia akkor az GC-zve lesz. Mi értelme volt akkor elötte inicializálni?
Ha új listát akarsz létrehozni, akkor érdemesebb lenne azt a metóduson belül megtenni és annak visszatérési értékeként visszaadni. Ebben az esetben viszont nem illik semmilyen bemenő paramétert megváltoztatni.
-
joysefke
veterán
Szerintem ez leginkább a vállalati Windowsok átka lesz.
Köze nincs a Windows-hoz. A Dell notebook (Precision 5540) egy szemét arra tervezték, hogy a 15-precre amire egy beszerzésért felelős vezető a kezébe veszi jó benyomást keltsen, nem arra, hogy ezt valaki 8 órában használni is akarja, főleg nem erőforrásigényes dolgokra.
Ha a Visual Studio beindul, (vagy bármi más) akkor a háttérfolyamatai felfalják a notit, pillanat alatt megeszi a turbó/hő-keretét és utána már csak 2.6GHz-en vagy alatta szerencsétlenkedik olyan hanggal mintha egy flex lenne. Es akkor már akkor sem fog felugrani 4.6GHz-re, ha olyan burstos folyamat van aminek tényleg kéne (UI vagy bármi aminek prioritása van a VS background taskokkal szemben).
Egyértelműen tervezési / beszerzési hibás ez a gép. Zabáló túlhevülő processzor egy vékony gyenge hűtésű házban.
Szerintem ez leginkább a vállalati Windowsok átka lesz.
Ezeken vállalati Windowst futtatnak. Az 5530-on konkrétan fagyott a Linux (nálunk). A Dell képzeletbeli operációs rendszerekhez fejleszti a gépeit?.
-
joysefke
veterán
válasz
martonx #9434 üzenetére
Hmm nekem egy i7 9850H -val szerelt 15"-os "business" Dell noti van. Nem az én ötletem volt a régit erre cserélni.
A legkisebb terhelésre is behangosodik, ha pedig komoly terhelés van (nagy repo+ VS-E + debuggolás), akkor olyan mintha flexelnének mellettem. Az órajeleket egy pillanat alatt visszaveszi 2.6GHz-ra -lehet hogy az alá is-, aztán még a MS Teams is akad rajta. Miközben órákon keresztül úgy üvölt hogy a saját gondolataimat sem hallom...
Valószínűnek tartom, hogy ha kipróbálom, a PC-mben lévő RyZEN 3100 is tényleges munka alatt agyonveri ezt a mobil i7-et. Biztosan nem fog sem üvölteni vagy 3.9GHz alá visszevenni az órejelét.
Mindenki számára intő példa legyen, aki azt hiszi hogy ezek a "business" laptopok bírják a terhelést...
-
joysefke
veterán
válasz
drsanya #9428 üzenetére
semmi köze a típusossághoz. var-ral is már megvan fordítási időben a változó típusa.
Egyrészt nincs sok haszna deklarációnál bal oldalra kiírni a típust ha az értékadásból már ránézésre látszik, hogy mi a típus.
Másrészt nehezíti a szerkesztést: lehet hogy le akarom cserélni a változó típusát vagy azon belül mondjuk egy generikus típusparamétert egy kompatibilisre stb. Ha bal oldalon fixen benne van a deklarációban a típus, akkor oda kell menni és manuálisan ki kell cserélni. Feleslegesen. LINQ-nél meg persze halál lenne. -
joysefke
veterán
kicsit off.
Van egy nyomorék céges laptopom ami üvölt mint egy turbina, de legalább lassú mint a csiga (9-gen top i7
) és fontolom hogy a privát gépemre költöztessem a munkát legalább akkor amikor otthonról dolgozom mert az kussban van és még az órajeleit is tudja tartani szemben a laptoppal.
SSD-t kéne bővítenem amin a céges VM+ VS lenne. Kérdés hogy a VS Entrprisenak mennyire kell a minnél gyorsabb SSD? Fordítás meg a kódanalízis mennyire szereti a gyorsabb SSD-t (WD black vagy Crucial P5) egy alsóbb kategóriással szemben (WD blue vagy Crucial P2)?
-
joysefke
veterán
Azure AD?
szvsz ezeket a tutorialokat lenne érdemes megnézni.
Alapvetően úgy működik a SSO, hogy van egy Identity Platform (IP) (e.g. Azure AD, vagy valami egyéb) aki a user adatbázist és az azonosításhoz szükséges információkat tartalmazza. Ez az IP ismeri a te alkalmazásodat, az ott be van regisztálva: egyebek mellett pld az IP nyilvántart az alkalmazáshoz egy redirect url-t amivel sikeres user-bejelentkeztetés után Http-redirectelheti a browsert vissza az apphoz.Az IP ezen felül nyilvántartja hogy az adott appnak a domain/tenant admin mit engedélyezett mihez milyen erősorrásokhoz legyen milyen hozzáférése/ vagy egyáltalán mihez legyen lehetősége a usertől hozzáférést kérni (admin consent-user consent).
Amikor a user be akar a Web-appodon jelentkezni, akkor a Web-app őt átirányítja (http-redirect) az IP bejelentkeztető oldalára, a user bejelentkezik. Ha szükséges akkor bejelentkezé után az IP a webalkalmazás nevében engedélyt kér a usertől az előre definiált adatok elérésére, a user ezt leokézhatja. Ha az IP boldog a bejelentkeztetéssel, akkor generál egy (vagy több) tokent. Ha OpenIdConnect a használt protokol akkor elsősorban egy ID-token generálódik (és esetleg másegyebek). Ez az ID token belekerül a Http-responsba amit az IP küld vissza a browsernek, egy Http redirect keretében amivel a usert visszaküldi as bejelentkeztetést kezdeményező Web-apphoz.
A WebApp az ID token birtokában annak tartalmából ellenőrizni tudja a böngészőt felhasználó user identitását.
=======
AzureAD-ra ingyen tudsz regisztrálni (Azure AD tenantot/domaint készíteni) ezután fogod és kipróbálod a kód sampleket (próbáltam működnek ootb), ezután megérted az OpenIdConnect use caseket (azonosítod a sajátodat) aztán úgy haladsz tovább. Ez az elmélet
NET + ASP Net Core jól működő middleware komponsnseket tartalmaz ezekhez
-
joysefke
veterán
válasz
DrojDtroll #9398 üzenetére
FormatException? esetleg az alkalmazás definiálhatja a saját típusait...
-
joysefke
veterán
válasz
alratar #9386 üzenetére
Mivel úgy tűnik, hogy a DateTime parsolással van a hiba, ezért meg kéne nézni hogy
1.
az SqlReaderből ki jön-e egyáltalán a rekord "Date" oszlophoz tartozó értéke, ha igen akkor2.
Megfelelő (az általad megadottal kompatibilis) formátumban jön-e ki3.
Megnézni, hogy a format string amit megadtál egyáltalán érvényes-e. Tippre nem: Custom date and time format strings | Microsoft Docs
A hónap az nagy 'M' a perc az kis 'm'4,
Amíg az egész nem működik addig külön-külön kéne a db-ből olvasást aztán annak parsolását tesztelni.Legjobb lenne erre valami wrapper...
-
joysefke
veterán
Ilyen dolgok miatt nem kell végigmenni az egész listán Erre pont jó a linq, amivel egyszerűen lekerdezhetetd, hogy a respomse.data lista elemei között van-e olyany akinek a felhasználó neve és jelszava egyezik.
Vagy akár eleve nem kéne a szervernek leküldenie a teljes usernév/pwd táblát -
joysefke
veterán
Elég naív és gyanútlan ez a RestAPI
de nem vezetett sikerre.
Ez túl tág.Gondolom egyszerre egy felhasználó akar bejelentkezni, a WinForms applikációdnak tehát elég lenne leellenőrizni, hogy a RestAPI-tól lekért listában benne van-e a megfelelő felhasználó, illetve ha igen akkor a bevitt jelszó megegyezik a listában szereplővel.
Jelenleg te végiglépdelsz a List<Felhasznalo>-n és minden elemére megnézed az egyezőséget és hívsz egy MessageBox.Show-t...
-
joysefke
veterán
Én fognám az androidos komponenseket, megnézném mit csinálnak, aztán azt, hogy ezekből mennyi érhető el Xamarin.Forms-ból cross platform megvalósítással pld https://docs.microsoft.com/hu-hu/xamarin/essentials/?WT.mc_id=docs-dotnet-xamarin
gondolom amennyire lehet egységesíteni szeretnéd a kódbázist
Aztán ez persze csak elmélet, nem csináltam ilyen portolást
-
joysefke
veterán
válasz
Tomi_78 #9342 üzenetére
programot írnék SharpDevelop környezetben
Ebben az izében? https://en.wikipedia.org/wiki/SharpDevelop#/media/File:SharpDevelop.png
Visual Studio Community ingyen van. -
joysefke
veterán
válasz
DrojDtroll #9337 üzenetére
public static int[,] Get4mIntArrBufferedSpan(string fileName)
{
var sw = new Stopwatch();
uint heigth = 2048;
uint width = heigth;
var result = new int[heigth, width];
var buffSize = sizeof(ushort) * heigth;
var buff = new byte[buffSize];
using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.None, bufferSize: 1024 * 1024))
{
sw.Start();
for (int w = 0; w < width; w++)
{
int chunk = 0;
while (chunk < buffSize)
chunk += fs.Read(buff, chunk, (int)buffSize - chunk);
var shortArr = MemoryMarshal.Cast<byte, ushort>(buff);
for (int h = 0; h < heigth; h++)
result[h, w] = shortArr[h];
}
sw.Stop();
Console.WriteLine($"{nameof(Get4mIntArrBufferedSpan)} took {sw.ElapsedMilliseconds}ms");
}
return result;
}
Nekem a fenti kód pontosan ugyanazt az eredmény tömböt dobja ki mint a te első metódusod. A különbség annyi, hogy a itt while ciklus megpróbál egyszerre 4096byteot (2048db ushort) kiolvasni a streamből, a kiolvasott byte tömböt castolja ushort-tömbre azzal pedig feltölti egy oszlopodat.
Szóval itt is rossz a tömb bejárási sorrendje, de a Stream.Read() metódus úgy tűnik, hogy ennyivel hatékonyabb, mint egyenként ushortokat olvasgatni. (nálam pontosan duplázódott a sebesség)
A fenti kódban ha a mátrix bejárási sorrendje "normalizálódna" akkor további 3x lenne gyorsabb. ==> tehát igen, itt a processzor fogja vissza a fájlműveletet
Ebben az esetben lenne értelme egyszerre 2048db elemnél többet is olvasni. Az még dobna rajta.
Új hozzászólás Aktív témák
● ha kódot szúrsz be, használd a PROGRAMKÓD formázási funkciót!
- Kerékpárosok, bringások ide!
- Dell notebook topic
- Milyen asztali (teljes vagy fél-) gépet vegyek?
- Steam, GOG, Epic Store, Humble Store, Xbox PC Game Pass, Origin Access, uPlay+, Apple Arcade felhasználók barátságos izgulós topikja
- Gurulunk, WAZE?!
- Futás, futópályák
- Bittorrent topik
- Honor Magic5 Pro - kamerák bűvöletében
- Poco X3 Pro - hardverfrissítés
- Napelem
- További aktív témák...
- Eladó MSI B650 GAMING PLUS WIFI Alaplap
- Eladó PNY GeForce RTX 4070 Ti SUPER 16GB videokártya
- Bomba ár! Asus Slate EP121 Tablet - Intel Core i5 I 4GB I 64GB SSD I 12" Touch I Cam I W10 I Gari!
- Bomba ár! HP EliteBook 2570P - i5-3GEN I 4GB I 320GB I DVD I 12,5" HD I W10 I Garancia!
- Bomba ár! HP EliteBook 2560P - i5-2GEN I 4GB I 320GB I 12,5" HD I W10 I Garancia!
- AKCIÓ! Acer Predator Triton Neo 16 15 notebook - Ultra 9 185H 32GB RAM 2TB SSD RTX 4070 WIN11
- ÁRGARANCIA! Épített KomPhone Ryzen 5 5600X 16/32/64GB RAM RTX 5060 8GB GAMER PC termékbeszámítással
- Xiaomi Redmi 12 Pro 5G 128GB, Kártyafüggetlen, 1 Év Garanciával
- Csere-Beszámítás! Asus Számítógép PC Játékra! R5 1600X / GTX 1080 8GB / 32GB DDR4 / 256SSD + 2TB HDD
- Azonnali készpénzes félkonfig / félgép felvásárlás személyesen / csomagküldéssel korrekt áron
Állásajánlatok
Cég: Promenade Publishing House Kft.
Város: Budapest
Cég: PC Trade Systems Kft.
Város: Szeged