Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Számos üzletági alkalmazás úgy van kialakítva, hogy több ügyféllel működjön együtt. Fontos az adatok védelme, hogy az ügyféladatok ne "kiszivárogjanak", és ne láthassák más ügyfelek és potenciális versenytársak. Ezek az alkalmazások "több-bérlősnek" minősülnek, mivel minden ügyfél az alkalmazás bérlőjének minősül saját adatkészlettel.
Figyelmeztetés
Ez a cikk egy helyi adatbázist használ, amely nem igényli a felhasználó hitelesítését. A termelésben használt alkalmazásoknak az elérhető legbiztonságosabb hitelesítési folyamatot kell használniuk. Az üzembe helyezett teszt- és éles alkalmazások hitelesítéséről további információt Biztonságos hitelesítési folyamatokcímű témakörben talál.
Fontos
Ez a dokumentum példákat és megoldásokat tartalmaz". Ezek nem "ajánlott eljárások", hanem inkább "munkamódszerek" az Ön számára.
Jótanács
A minta forráskódját a GitHubon tekintheti meg
Több-bérlős működés támogatása
Több megközelítés is létezik a több-bérlős alkalmazások megvalósítására. Az egyik gyakori megközelítés (ez néha követelmény) az egyes ügyfelek adatainak külön adatbázisban való megőrzése. A séma ugyanaz, de az adatok ügyfélspecifikusak. Egy másik módszer az adatok ügyfél általi particionálása egy meglévő adatbázisban. Ezt megteheti úgy, hogy egy táblában lévő oszlopot használ, vagy több sémában hoz létre táblát, minden bérlőhöz külön sémát létrehozva.
| Megközelítés | Bérlői oszlop? | Séma bérlőnként? | Több adatbázis? | EF Core-támogatás |
|---|---|---|---|---|
| Diszkriminátor (oszlop) | Igen | Nem | Nem | Globális lekérdezésszűrő |
| Adatbázis bérlőnként | Nem | Nem | Igen | Konfiguráció |
| Séma bérlőnként | Nem | Igen | Nem | Nem támogatott |
A bérlőnkénti adatbázis-megközelítés esetében a megfelelő adatbázisra való váltás ugyanolyan egyszerű, mint a megfelelő kapcsolati sztring megadása. Ha az adatokat egyetlen adatbázisban tárolják, egy globális lekérdezésszűrővel automatikusan szűrheti a sorokat a bérlőazonosító oszlop alapján, biztosítva, hogy a fejlesztők ne írjanak véletlenül olyan kódot, amely hozzáfér más ügyfelek adataihoz.
Ezeknek a példáknak a legtöbb alkalmazásmodellben jól kell működniük, beleértve a konzolt, a WPF-et, a WinForms-t és ASP.NET Core-alkalmazásokat. A Blazor Server-alkalmazások különös figyelmet igényelnek.
A Blazor Server-alkalmazások és a gyár élete
Az Entity Framework Core Blazor-alkalmazásokban való használatához ajánlott a DbContextFactory regisztrálása, majd az egyes műveletek új példányának DbContext létrehozása. Alapértelmezettként a gyári beállítás egy szinguleton, így csak egy másolat létezik az alkalmazás összes felhasználója számára. Ez általában rendben van, mert bár a gyár megosztott, az egyes DbContext példányok nem.
Több-bérlős környezet esetén azonban a kapcsolati karakterlánc változhat felhasználónként. Mivel a gyár gyorsítótárazza a konfigurációt ugyanolyan élettartammal, emiatt minden felhasználó ugyanazt a konfigurációt osztja meg. Ezért az élettartamot a következőre kell módosítani Scoped: .
Ez a probléma nem fordul elő a Blazor WebAssembly-alkalmazásokban, mert a singleton hatóköre a felhasználóra terjed ki. A Blazor Server-alkalmazások viszont egyedi kihívást jelentenek. Bár az alkalmazás egy webalkalmazás, a SignalR használatával való valós idejű kommunikáció "életben tartja". A munkamenet felhasználónként jön létre, és a kezdeti kérésen túl tart. Felhasználónként új gyárat kell megadni az új beállítások engedélyezéséhez. Ennek a speciális gyárnak az élettartama hatókörrel van korlátozva, és egy új példányt hoznak létre felhasználói munkamenetenként.
Példamegoldás (önálló adatbázis)
Lehetséges megoldás egy egyszerű ITenantService szolgáltatás létrehozása, amely kezeli a felhasználó aktuális bérlőjének beállítását. Visszahívásokat biztosít, így a kód értesítést kap a bérlő változásairól. A megvalósítás (az egyértelműség kedvéért kihagyott visszahívásokkal) a következőképpen nézhet ki:
namespace Common
{
public interface ITenantService
{
string Tenant { get; }
void SetTenant(string tenant);
string[] GetTenants();
event TenantChangedEventHandler OnTenantChanged;
}
}
Ezután DbContext kezelheti a több-bérlős rendszert. A megközelítés az adatbázis-stratégiától függ. Ha az összes bérlőt egyetlen adatbázisban tárolja, valószínűleg egy lekérdezésszűrőt fog használni. A ITenantService függőség injektálással van átadva a konstruktorhoz, és a bérlőazonosító feloldására és tárolására használják.
public ContactContext(
DbContextOptions<ContactContext> opts,
ITenantService service)
: base(opts) => _tenant = service.Tenant;
A OnModelCreating metódust felülírják a lekérdezésszűrő megadásához:
protected override void OnModelCreating(ModelBuilder modelBuilder)
=> modelBuilder.Entity<MultitenantContact>()
.HasQueryFilter(mt => mt.Tenant == _tenant);
Ez biztosítja, hogy minden lekérdezés a bérlőre legyen szűrve minden kérés esetén. Az alkalmazáskódban nincs szükség szűrésre, mert a globális szűrő automatikusan alkalmazva lesz.
A bérlőszolgáltató, és DbContextFactory az alkalmazás indításakor a következőképpen van konfigurálva, példaként az Sqlite-t használva:
builder.Services.AddDbContextFactory<ContactContext>(
opt => opt.UseSqlite("Data Source=singledb.sqlite"), ServiceLifetime.Scoped);
Figyelje meg, hogy a szolgáltatás élettartama a következővel ServiceLifetime.Scopedvan konfigurálva: . Ez lehetővé teszi, hogy függőséget vegyen fel a bérlőszolgáltatótól.
Megjegyzés
A függőségeknek mindig a singleton felé kell haladniuk. Ez azt jelenti, hogy egy Scoped szolgáltatás függhet egy másik Scoped szolgáltatástól vagy Singleton szolgáltatástól, de a Singleton szolgáltatás csak más Singleton szolgáltatásoktól függhet: Transient => Scoped => Singleton.
Több séma
Figyelmeztetés
Ezt a forgatókönyvet az EF Core nem támogatja közvetlenül, és nem ajánlott megoldás.
Egy másik megközelítésben ugyanaz az adatbázis képes kezelni tenant1 és tenant2 táblázatsémákat használni.
-
Bérlő1 -
tenant1.CustomerData -
Bérlő2 -
tenant2.CustomerData
Ha nem az EF Core-t használja az adatbázis-frissítések migrálással való kezelésére és már rendelkezik többsémai táblákkal, felülírhatja a sémát egy DbContext ezen módon a OnModelCreating környezetben (a tábla CustomerData sémája a bérlőhöz van rendelve):
protected override void OnModelCreating(ModelBuilder modelBuilder) =>
modelBuilder.Entity<CustomerData>().ToTable(nameof(CustomerData), tenant);
Több adatbázis és kapcsolati karakterlánc
A több adatbázisverziót úgy implementáljuk, hogy minden bérlőhöz egy másik kapcsolati sztringet ad át. Ez indításkor konfigurálható a szolgáltató meghatározásával és a kapcsolati sztring ennek segítségével történő létrehozásával. A appsettings.json konfigurációs fájlhoz bérlői szakaszonként egy kapcsolati sztring kerül hozzáadásra.
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"ConnectionStrings": {
"TenantA": "Data Source=tenantacontacts.sqlite",
"TenantB": "Data Source=tenantbcontacts.sqlite"
},
"AllowedHosts": "*"
}
A szolgáltatás és a konfiguráció egyaránt a következőbe DbContextvan injektálva:
public ContactContext(
DbContextOptions<ContactContext> opts,
IConfiguration config,
ITenantService service)
: base(opts)
{
_tenantService = service;
_configuration = config;
}
A bérlőt ezután a kapcsolati sztring OnConfiguring keresésére használják:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var tenant = _tenantService.Tenant;
var connectionStr = _configuration.GetConnectionString(tenant);
optionsBuilder.UseSqlite(connectionStr);
}
Ez a legtöbb forgatókönyv esetében jól működik, hacsak a felhasználó nem tud bérlőket váltani ugyanabban a munkamenetben.
Bérlőváltás
Az előző konfigurációban a több adatbázisra vonatkozó beállítások a Scoped szinten gyorsítótárba kerülnek. Ez azt jelenti, hogy ha a felhasználó módosítja a bérlőt, a beállítások nem lesznek újraértékelve, így a bérlő változása nem jelenik meg a lekérdezésekben.
Az egyszerű megoldás, amikor lehetőség van a bérlő megváltoztatására, az élettartamot Transient. beállítani. Ez biztosítja, hogy a bérlőt újraértékelik a kapcsolati karakterlánccal együtt minden alkalommal, amikor a DbContext kérést kezdeményezik. A felhasználó a kívánt gyakran válthat bérlőket. Az alábbi táblázat segít kiválasztani, hogy melyik élettartam a legérthetőbb a gyár számára.
| Forgatókönyv | Önálló adatbázis | Több adatbázis |
|---|---|---|
| A felhasználó egyetlen bérlőben marad | Scoped |
Scoped |
| A felhasználó válthat bérlőket | Scoped |
Transient |
Az alapértelmezett beállítás Singleton akkor is értelmes, ha az adatbázis nem veszi fel a felhasználó hatókörébe tartozó függőségeket.
Teljesítményjegyzetek
Az EF Core úgy lett kialakítva, hogy a DbContext példányok gyorsan, a lehető legkisebb terheléssel példányosíthatók legyenek. Ezért a műveletenkénti új DbContext létrehozásnak általában rendben kell lennie. Ha ez a megközelítés befolyásolja az alkalmazás teljesítményét, fontolja meg a DbContext-készletezés használatát.
Következtetés
Ez a munka útmutató az EF Core-alkalmazásokban a több-bérlős alkalmazások implementálásához. Ha további példákat vagy forgatókönyveket szeretne, vagy visszajelzést szeretne küldeni, nyisson meg egy problémát , és hivatkozzon erre a dokumentumra.