2016-05-13 14 views
10

Ho due tabelle:Come copiare dati da SQL oggetto di C# modello proprietà

  • Impiegato: Id, Name, DepartmentId
  • Dipartimento: Id, Name

Employee.cs:

public int Id {get;set;} 
public string Name {get;set;} 
public int DepartmentId {get;set;} 

Department.cs:

public int Id {get;set;} 
public string Name {get;set;} 

ViewModel: EmployeeDepartmentVM:

public Department department {get;set;} 
public List<Employee> employees {get;set;} 

a partecipare a queste due tabelle ho scritto questo codice:

SELECT E.* , D.Id as DId , D.Name as DName 
    from [Employee] as E 
    LEFT OUTER JOIN [Department] as D 
    ON E.DepartmentId = D.Id 
    where D.Id = 1 

Come faccio ad avere il tipo EmployeeDepartmentVM da quanto sopra interrogare?

lo so se scrivo un modello come il mio problema sarà risolto:

public int Id {get;set;} 
public string Name {get;set;} 
public int DepartmentId {get;set;} 
public int DId {get;set;} 
public string Name {get;set;} 

Ma io non voglio scrivere modello extra. Semplicemente desideri associare i dati delle query al tipo EmployeeDepartmentVM.

+1

È possibile utilizzare la riflessione per riempire le proprietà. http://stackoverflow.com/questions/1089123/setting-a-property-by-reflection-with-a-string-value –

+1

Quando LEFT JOIN, inserisci le condizioni del lato destro nella clausola ON per ottenere il comportamento true left join . (Quando in WHERE si ottiene un risultato di inner join regolare.) I.e do '... ON E.DepartmentId = D.Id AND D.Id = 1'. – jarlh

+1

Perché non ti piace usare EF ..? Devi scrivere altro codice, se non stai usando questo ORM .. – Karthick

risposta

7

Davvero non vedo qual è la sfida. La definizione EmployeeDepartmentVM implica che è necessario raggruppare il set di risultati da Department. Supponendo che il set di risultati non sia ordinato, può essere ottenuto semplicemente mantenendo un dizionario per localizzare i modelli di visualizzazione dei reparti già aggiunti durante la lettura.

che porta a qualcosa di simile:

static List<EmployeeDepartmentVM> GetEmployeeDepartmentVMList(DbCommand command) 
{ 
    var resultById = new Dictionary<int, EmployeeDepartmentVM>(); 
    using (var reader = command.ExecuteReader()) 
    { 
     var employeeIdCol = reader.GetOrdinal("Id"); 
     var employeeNameCol = reader.GetOrdinal("Name"); 
     var departmentIdCol = reader.GetOrdinal("DId"); 
     var departmentNameCol = reader.GetOrdinal("DName"); 
     while (reader.Read()) 
     { 
      var departmentId = reader.GetInt32(departmentIdCol); 
      EmployeeDepartmentVM result; 
      if (!resultById.TryGetValue(departmentId, out result)) 
      { 
       result = new EmployeeDepartmentVM 
       { 
        department = new Department(), 
        employees = new List<Employee>() 
       }; 
       result.department.Id = departmentId; 
       result.department.Name = reader.GetString(departmentNameCol); 
       resultById.Add(departmentId, result); 
      } 
      var employee = new Employee(); 
      employee.Id = reader.GetInt32(employeeIdCol); 
      employee.Name = reader.GetString(employeeNameCol); 
      employee.DepartmentId = departmentId; 
      result.employees.Add(employee); 
     } 
    } 
    return resultById.Values.ToList(); 
} 

Alcune cose da notare. Nella modalità scritta, la query SQL implica che i campi relativi al reparto possono essere nulli (LEFT OUTER JOIN). Tuttavia, la clausola WHERE e anche il modello Employee (campo DepartmentId non annullabile) implicano che non può accadere. Se l'intento è quello di includere i dipartimenti senza dipendenti, quindi meglio cambiare il join a RIGHT OUTER e utilizzare qualcosa di simile:

// ... 
if (reader.IsDBNull(employeeIdCol)) continue; 
var employee = new Employee(); 
// ... 

EDIT: Per completezza, ecco un altro approccio. E 'simile al modo in EF materializza query simili e non ha bisogno dizionario temporanea, ma richiede l'ingresso impostato per essere ordinato dal PK della tabella master, quindi è necessario aggiungere

ORDER BY D.Id 

alla fine del vostro SQL . I database possono fornire questo tipo di ordine in modo semplice ed efficiente, e il beneficio di questa soluzione è che consente l'esecuzione differita e non richiede l'elaborazione dell'intero set per iniziare a restituire i risultati. Non è essenziale se vuoi solo ottenere una lista, ma può essere utile in altri scenari.

static IEnumerable<EmployeeDepartmentVM> GetEmployeeDepartmentVMs(DbCommand command) 
{ 
    using (var reader = command.ExecuteReader()) 
    { 
     var employeeIdCol = reader.GetOrdinal("Id"); 
     var employeeNameCol = reader.GetOrdinal("Name"); 
     var departmentIdCol = reader.GetOrdinal("DId"); 
     var departmentNameCol = reader.GetOrdinal("DName"); 
     for (bool more = reader.Read(); more;) 
     { 
      var result = new EmployeeDepartmentVM 
      { 
       department = new Department(), 
       employees = new List<Employee>() 
      }; 
      result.department.Id = reader.GetInt32(departmentIdCol); 
      result.department.Name = reader.GetString(departmentNameCol); 
      do 
      { 
       if (reader.IsDBNull(employeeIdCol)) continue; 
       var employee = new Employee(); 
       employee.Id = reader.GetInt32(employeeIdCol); 
       employee.Name = reader.GetString(employeeNameCol); 
       employee.DepartmentId = result.department.Id; 
       result.employees.Add(employee); 
      } 
      while ((more = reader.Read()) && reader.GetInt32(departmentIdCol) == result.department.Id); 
      Debug.Assert(!more || reader.GetInt32(departmentIdCol) > result.department.Id); // Sanity check 
      yield return result; 
     } 
    } 
} 

per ottenere una lista come nel primo approccio, basta aggiungere ToList() dopo la chiamata, ad esempio,

var result = GetEmployeeDepartmentVMs(command).ToList(); 
+0

ya. Per me funziona. Una domanda. Posso usare List invece di Dictionary? –

+1

È possibile, ma sarà inefficiente se non si applica il filtro di reparto. Le implementazioni di raggruppamento di solito utilizzano una sorta di struttura dati hash (come il dizionario) o set di risultati ordinati (come EF). Il dizionario è solo temporaneo, come puoi vedere, lo sto convertendo in lista alla fine. –

Problemi correlati