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();
È possibile utilizzare la riflessione per riempire le proprietà. http://stackoverflow.com/questions/1089123/setting-a-property-by-reflection-with-a-string-value –
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
Perché non ti piace usare EF ..? Devi scrivere altro codice, se non stai usando questo ORM .. – Karthick