2016-05-13 33 views
10

Verileri Nasıl Kopya:İki tablo var C# Modeli Sql nesneden özellik

  • Çalışan: Id, Name, DepartmentId
  • Bölüm: Id, Name

Employee.csadı:

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: Nasıl yukarıdan EmployeeDepartmentVM türü alırım

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 

:

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

Bu kodu yazdım bu iki tablo Katılım için sorgu? Benim sorun gibi bir model yazarsanız bildiğim

çözülecektir:

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;} 

Ama ekstra bir model yazmak istemiyorum. Sadece EmployeeDepartmentVM türüne sorgu verilerini bağlamak istiyorum.

+1

Özellikleri doldurmak için yansımayı kullanabilirsiniz. http://stackoverflow.com/questions/1089123/setting-a-property-by-reflection-with-a-string-value –

+1

LEFT JOIN, gerçek sağa katılma davranışını düzeltmek için ON yan tümcesinde sağ taraftaki tablo koşullarını koy. . (Ne zaman WHERE'de düzenli iç katılma sonucu elde edersiniz.) I.e '… EEepartmentId = D.Id AND D.Id = 1'. – jarlh

+1

Neden EF .. kullanmak istemiyorsunuz? Bu ORM'yi kullanmıyorsanız daha fazla kod yazmalısınız .. – Karthick

cevap

7

Gerçekten meydan okuma görmüyorum. EmployeeDepartmentVM tanımında, sonuç kümesini Department ile gruplandırmanız gerektiği anlamına gelir. Sonuç kümesinin sırasız olduğunu varsayarak, okuma sırasında zaten eklenen bölümlerin görünüm modellerini bulmak için bir sözlüğü tutmak yeterlidir. Unutulmaması gereken

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(); 
} 

Bazı şeyler: Böyle bir şey neden

. Yazılan yol, SQL sorgunuz, Bölüm ile ilgili alanların null olabileceğini ima eder (LEFT OUTER JOIN). Ancak, WHERE yan tümcesi ve ayrıca Çalışan modeli (null olmayan DepartmentId alanı), bunun gerçekleşemeyeceğini ima eder. niyet hiçbir çalışanı ile bölümleri dahil etmek ise, o zaman daha iyi böyle bir şey RIGHT OUTER katılmak ve kullanımı değiştirin:

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

EDIT: tamlığı için, burada başka bir yaklaşımdır. Eğer SQL sonunda

ORDER BY D.Id 

eklemem gerekiyor EF benzer sorguları gerçekleşmesi ve geçici sözlüğü gerekmez benzer şekilde, ama usta tablonun PK tarafından sipariş edilmesi set girişi gerektirir, bu yüzden . Veritabanları, bu tür bir siparişi kolayca ve verimli bir şekilde sağlayabilir ve bu çözümün yararı, ertelenmiş uygulamaya izin vermesi ve sonuçların döndürülmesi için bütün kümenin işlenmesini gerektirmemesidir. Sadece bir liste almak istiyorsanız, ancak diğer senaryolarda yararlı olabilir.

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; 
     } 
    } 
} 

sadece örneğin çağrısından sonra ToList() ekleyin birinci yaklaşımda olduğu gibi bir listesini almak için

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

ya. Benim için çalışıyor. Bir soru. Sözlük yerine Liste kullanabilir miyim? –

+1

Yapabilirsin, ancak departman filtresi uygulamıyorsan verimsiz olacak. Gruplama uygulamaları genellikle bir tür karma veri yapısı (Sözlük gibi) veya sıralanmış sonuç kümeleri (EF gibi) kullanır. Sözlük sadece geçicidir, gördüğünüz gibi, sonunda listeye dönüştürüyorum. –

İlgili konular