Creazione di query diverse su DB per un oggetto

0

Nella mia app sto usando EF. Ho il servizio che può fornire alcune informazioni e clienti che vogliono chiedere tali informazioni. Immaginiamo di avere un utente, che ha l'indirizzo, l'elenco delle attrezzature, l'elenco degli abbonamenti, l'elenco dei saldi. Ogni saldo ha l'elenco delle operazioni.

public class User
{
    public User()
    {
        Equipments = new HashSet<Equipment>();
        Balances = new HashSet<Balance>();
        Subscriptions = new HashSet<Subscription>();
    }

    public long Id { get; set; }
    public string LastName { get; set; }

    public DateTime DOB { get; set; }

    public long AddressId { get; set; }
    public Address Address { get; set; }

    public ICollection<Equipment> Equipments { get; set; }

    public ICollection<Balance> Balances { get; set; }

    public ICollection<Subscription> Subscriptions { get; set; }
}

public class Equipment
{
    public long Id { get; set; }
    public string Model { get; set; }
    public int StateId { get; set; }

    public long UserId { get; set; }

    public User User { get; set; }
}

public class Balance
{
    public Balance()
    {
        Operations = new HashSet<BalanceOperation>();
    }
    public long Id { get; set; }
    public decimal Amount { get; set; }
    public int CurrencyId { get; set; }

    public long UserId { get; set; }

    public User User { get; set; }

    public ICollection<BalanceOperation> Operations { get; set; }
}

public class BalanceOperation
{
    public long Id { get; set; }

    public DateTime OperationDate { get; set; }

    public long BalanceId { get; set; }
    public Balance Balance { get; set; }
}

public class Address
{
    public int Id { get; set; }
    public string City { get; set; }
    public int HouseNumber { get; set; }
}

public class Subscription
{
    public long Id { get; set; }

    public int ServiceId { get; set; }

    public bool IsActive { get; set; }

    public long UserId { get; set; }

    public User User { get; set; }
}

Inoltre ho un UserInfo DTO, che può contenere tutte quelle informazioni. I clienti vogliono usare gli UserDto in diversi punti dell'app. Ma non hanno bisogno di tutte le informazioni tutto il tempo. Ad esempio, a volte ho bisogno solo dell'utente con i suoi saldi senza operazioni. A volte - solo attrezzature e abbonamenti. A volte - equilibri con operazioni. Quindi, quello che voglio è che il client utilizzi un metodo per ottenere informazioni fornendo una sorta di include.

int includes = (int)(IncludeEnum.Adress | IncludeEnum.Subscriptions);
UserInfo userInfo = _service.GetUserInfo(id, includes);

Il problema è come costruire l'architettura del server, quali modelli usare ecc. Dipende da Include Costruirò diverse query su DB e riempirò UserInfo in modo corretto. Il server deve fornire informazioni e non fornire le informazioni non necessarie e nemmeno a quelle informazioni nel DB. Quindi ridurrebbe il numero di richieste. In EF posso usare Include () per ottenere oggetti correlati. A volte posso creare query utilizzando LINQ (da ... join ... select). O forse tutti i miei pensieri sono sbagliati? E devo fare tutte le cose in modo diverso?

    
posta daewoosh 27.03.2017 - 10:24
fonte

2 risposte

1

La tua app sembra essere molto centrale per l'utente (o forse questa è solo una parte dell'app), ma questo è un segno che potresti avere troppo nella classe User, quindi suddividi questi elenchi in altre classi.

Esempio: saldi Non conosco la tua app, ma normalmente gli utenti non riescono a gestire direttamente i saldi dei loro account. L'utente possiede pochissime regole per la gestione degli account.

Class Balance Operations {
   GetUserBalances (User) {
   }

}

Chiamalo come vuoi e restituisci la lista. In questo modo puoi avere una logica che guida il recupero dei saldi dei conti. Se hai mai bisogno di ottenere i saldi da qualcosa di diverso dall'utente, questo è dove andrebbe.

Lo farei per l'attrezzatura e creare qualcosa chiamato inventario. GetUserEquipment (Utente). Quindi se vuoi recuperare per modello o gruppo di utenti, team, società o altro, questo è dove va.

Si sta tentando di fare in modo che la classe utente faccia tutto ciò che potrebbe coinvolgere un utente, ma a un certo punto (e penso che tu sia lì), ridisegna e sposta alcune cose nelle proprie classi.

    
risposta data 27.03.2017 - 16:11
fonte
0

TL; DR prova prima con tutti i dati e misura le prestazioni.

La tua paura che il ripristino di tutti i dati utente (modello "utente grasso") dal database sia troppo lento? Dalla tua descrizione, il lavoro che il DBMS (sto assumendo un RDBMS qui) farà qui è abbastanza comune, e non dovrebbe essere un problema di rendimento.

Sicuramente l'utilizzo di un solo modello per gli utenti porterebbe a un design molto più semplice dal lato dell'applicazione. L'utilizzo di molti modelli diversi per i tuoi utenti ("utenti magri") complica anche il codice dei tuoi clienti. Devono sapere che tipo di DTO possono / dovrebbero chiedere in un dato momento.

Inoltre, presumo che non ci siano problemi di sicurezza qui (come il fatto che devi nascondere le informazioni sui Saldi da alcuni dei tuoi clienti e Indirizzi da altri).

Nota: potreste scoprire che il miglior bilanciamento è quello di dividere il modello utente, ma solo per quanto riguarda alcuni aspetti. Ad esempio, iscrizioni separate a un modello separato (denominato UserSubscription o qualcosa del genere) che è correlato all'utente, ma non è un utente. Ciò dipenderà dai casi d'uso e dagli importi dei dati effettivi.

Corso di azione consigliato:

  1. crea un database di test, il più vicino possibile alle specifiche di produzione.
  2. popola con dati fittizi. Utilizzare un moltiplicatore di sicurezza. Per esempio. le tue specifiche sono per 100 000 utenti: crea 500 000 utenti fittizi, tutti con 2 indirizzi e così via. Ricorda l'indicizzazione corretta.
  3. Crea una query SQL UNISCA tutti i dati necessari all'applicazione.
  4. Esegui alcune query e prendi nota dei tempi di esecuzione. (Se sembrano lenti, consulta il tuo DBA).
  5. Utilizza la tua applicazione per eseguire questa query. Prendi nota dei tempi.
  6. Se i tempi sono accettabili, utilizza il modello "utente grasso".
  7. In caso contrario, crea una query simile per un modello "skinny user", ad es. solo nome utente e indirizzi.
  8. confronta i tempi di esecuzione come prima
  9. se è accettabile, dividi il modello Utente. In caso contrario, si verificano problemi più profondi da qualche parte (rete, configurazione DBMS, ecc.)

Dichiarazione di non responsabilità: non ho usato LinQ, ma per quanto ne so, non dovrebbe avere importanza dal punto di vista dell'architettura.

    
risposta data 27.03.2017 - 11:08
fonte

Leggi altre domande sui tag