Il modo migliore per convalidare le proprietà della classe

4

Sfondo:

Ho un file CSV, che devo preparare e convalidare ogni elemento in ogni riga e creare una raccolta di una classe, con dati validi.

vale a dire Il file CSV ha il seguente aspetto:

   EmpID,FirstName,LastName,Salary
    1,James,Help,100000
    2,Jane,Scott,1000
    3,Mary,Fraze,10000

La classe ha il seguente aspetto:

public class Employees
{
    public int EmpID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Salary { get; set; }
    public string ErrorReason { get; set; }
}

Ecco le convalide richieste per ciascun campo:

  • EmpID:

    • È un campo obbligatorio, quindi non può essere nullo o vuoto
    • Dovrebbe essere solo un numero intero
    • Dovrebbe essere non più di 2 cifre
    • Dovrebbe essere presente nel database (interrogare quel database e verificare se un dipendente esce con questo empid.
  • FirstName (stessa validazione per LastName):

    • È un campo obbligatorio, quindi non può essere nullo o vuoto
    • Dovrebbero essere solo alfabeti.
    • Non sono ammessi più di 30 caratteri
  • Stipendio:

    • È un campo obbligatorio, quindi non può essere nullo o vuoto
    • Dovrebbe essere un decimale.

Per raggiungere questo obiettivo, ecco il mio approccio:

  1. Leggi il file CSV riga per riga
  2. Per ciascun elemento, EmpId, FirstName ... etc effettua le convalide richieste chiamando i singoli metodi con logica di convalida. per esempio: public bool ValidateIsDecimal (valore stringa) {} public bool ValidateIsEmpIdExists (valore stringa) {} etc
  3. Se valido, inserisci la proprietà corrispondente della classe "Dipendenti".
  4. Se NON VALIDO, riempire la proprietà "ErrorReason", con il motivo appropriato per ciò che ha causato il fallimento della convalida (ad esempio: il file richiesto mancava o il tipo di dati non è decimale, ecc.)
  5. Aggiungi questa classe alla collezione Dipendenti (es .: Elenco)

Quindi, la mia domanda è, è questo l'approccio giusto, o c'è qualche altro modo migliore / più pulito di convalidare le proprietà della classe.

    
posta user2697452 09.01.2014 - 19:19
fonte

4 risposte

2

Se avessi bisogno di inserire dati e catturare errori, probabilmente farei qualcosa di più simile a:

public class Employee
{
    public int EmpID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Salary { get; set; }
}

public class ErrorEmployee : Employee
{
    public string[] ErrorReason { get; set; }
}
  1. Leggi il file CSV riga per riga
  2. Per ciascun elemento, EmpId, FirstName, ecc., eseguono le convalide richieste chiamando i singoli metodi con logica di convalida. es: public bool ValidateIsDecimal (valore stringa) {} public bool ValidateIsEmpIdExists (valore stringa) {} ecc.
  3. Se valido, inserisci la proprietà corrispondente della classe "Dipendenti". Aggiungi questa classe alla collezione Dipendenti (es .: Elenco)
  4. Se NON VALIDO, riempire la proprietà "ErrorReason", con il motivo appropriato per ciò che ha causato il fallimento della convalida (ad esempio: il file richiesto mancava o il tipo di dati non è decimale, ecc.) Aggiungi questa classe alla raccolta ErrorEmployees (es .: Elenco)

Non vorrei inquinare il normale oggetto Dipendente (singolare, usa il plurale per una collezione di essi) con messaggi di errore. Come nella nota precedente, controlla la libreria FluentValidation per la convalida e acquisisci un elenco di errori piuttosto che il primo trovato.

    
risposta data 09.01.2014 - 20:48
fonte
3

Questo è un problema abbastanza semplice, quindi non c'è molto che tu possa fare di sbagliato in questo. Il tuo approccio sembra perfetto.

L'unica cosa che ho notato potrebbe essere negativa è che stai interrogando DB per ogni riga. Sarebbe meglio se interrogassi il DB solo una volta con tutti gli ID. Ma supponendo che solo 100 righe siano possibili, questo non dovrebbe essere un problema. Ma almeno scriverei un commento questo potrebbe essere un problema in futuro.

    
risposta data 09.01.2014 - 19:26
fonte
2

Tre classi

  • CSVLine o string[]
  • dipendenti
  • Validator

CSVLine:

{
    public int LineNumber {get; set;}
    public string EmpID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Salary { get; set; }
}
  • Leggi la riga in CSVLine
  • Chiama i metodi di convalida appropriati sulle proprietà CSVLine o sugli elementi dell'array come necessario
  • Se è valido, crea un Dipendente che passa nel CSVLine o nell'array di stringhe

Se non è valido, è possibile registrare la riga CSV e gli errori di convalida su un file di rifiuto. Puoi convalidare tutti gli attributi o fallire velocemente e fermarti al primo errore. Sta a te. Inoltre, vi è l'opportunità di rendere CSV una struttura generica, come una stringa [] se non si desidera che i campi denominati in CSVLine e solo passare gli elementi dell'array come necessario per il validatore. Un array può essere una scelta migliore perché puoi convalidare anche il numero di elementi che ha (anche in questo caso 4).

Il validatore potrebbe anche essere un'interfaccia in modo da poter creare molti diversi tipi di validatori. Oppure puoi semplicemente avere una classe se questo è l'unico file con cui hai a che fare.

    
risposta data 09.01.2014 - 21:51
fonte
1

È abbastanza semplice, a meno che non ci siano ulteriori complicazioni che non hai elencato. Qualcosa di semplice come questo (pseudocodice) farà:

var customers = File.ReadAllLines("...")
    .AsParallel()
    .Select(l => l.Split(new char[] { ',' }))
    .Where(s => Tuple.Create(
        validateId(s[0]), 
        validateFirstName(s[1]), 
        validateLastName(s[2]),  
        validateSalary(s[3])))
    .Select(t => new Customer(t.Item1, t.Item2, t.Item3, t.Item4));

L'unica sfumatura qui è che validateXYZ convaliderà e restituirà anche il tipo corretto.

Per quanto riguarda "ErrorReason", riempire i dati non validi e quindi una ragione per i dati non validi sembra una cattiva idea.

Ho scritto query più complicate di così usando questo metodo esatto su file con milioni di righe in cui viene completato in pochi secondi. Se disponi di più dati, potrebbe esserci più lavoro da fare.

(btw: per questi tipi di problemi, linqpad è tuo amico).

    
risposta data 09.01.2014 - 19:52
fonte

Leggi altre domande sui tag