2011-02-14 22 views
10

Bu oldukça belirsiz/öznel bir sorudur. Bunun, ajax çağrılarını kullanarak tarayıcıya veri göndermenin/almanın en iyi yolu olup olmadığını bilmek istiyorum. Arka uç web servisinde, varlık çerçevesini kullanmak istiyorum. Aşağıda iki örnek işlev vardır.Varlık Çerçevesi ve Javascript Etkileşimi Nasıl İyileştirilir

"En iyi" ölçütleri yazma kodunun, okunabilir kodun ve sağlam mimarinin hızıdır.

Her türlü geri bildiriminiz, öneri ve yorumunuz için teşekkür ederiz.

alın Fonksiyon

[WebMethod] 
public AjaxEmployee EmployeeGetById(int employeeID, bool getTimeOff) 
{ 
    using (Time_TrackerEntities ctx = new Time_TrackerEntities()) 
    { 
     var results = from item in ctx.Employees 
         where item.ID == employeeID 
         orderby item.Last_Name 
         select new AjaxEmployee 
         { 
          ID = item.ID, 
          Employee_ID = item.Employee_ID, 
          First_Name = item.First_Name, 
          Middle_Name = item.Middle_Name, 
          Last_Name = item.Last_Name, 
          Supervisor_ID = item.Supervisor_ID, 
          Active = item.Active, 
          Is_Supervisor = item.Is_Supervisor 
         }; 
     var emp = results.FirstOrDefault(); 
     if (getTimeOff) 
     { 
      var results2 = from item2 in ctx.Time_Off 
          where item2.Employee_ID == emp.Employee_ID 
          select new AjaxTime_Off 
          { 
           ID = item2.ID, 
           Employee_ID = item2.Employee_ID, 
           Date_Off = item2.Date_Off, 
           Hours = item2.Hours 
          }; 
      emp.Time_Off = results2.ToList<AjaxTime_Off>(); 
     } 

     return emp; 
    } 
} 

kaydet Fonksiyonu

[WebMethod] 
public bool EmployeeSave(AjaxEmployee emp) 
{ 
    using (Time_TrackerEntities ctx = new Time_TrackerEntities()) 
    { 
     var results = from item in ctx.Employees 
         where item.ID == emp.ID 
         select item; 

     var myEmp = results.FirstOrDefault(); 
     if (myEmp == null) 
     { 
      myEmp = new Employee(); 
      ctx.Employees.AddObject(myEmp); 
     } 

     myEmp.Employee_ID = emp.Employee_ID; 
     myEmp.First_Name = emp.First_Name; 
     myEmp.Middle_Name = emp.Middle_Name; 
     myEmp.Last_Name = emp.Last_Name; 
     myEmp.Supervisor_ID = emp.Supervisor_ID; 
     myEmp.Active = emp.Active; 
     myEmp.Is_Supervisor = emp.Is_Supervisor; 

     return ctx.SaveChanges() > 0; 
    } 
} 
+0

Neden ayrı bir AjaxEmployee sınıfı var? Çalışanlarınızın varlığının bir projeksiyonu mu? –

+0

Ayrı sınıf, javascript'e gönderirken JSON'a daha iyi serileştirmektir.Çalışan ve Time_Off kaydı arasında bir ilişki olduğu için, serileştirme aşağıdakilere göre düzgün bir şekilde gerçekleşmez: http://mytechworld.officeacuity.com/?p=577 – Sam

cevap

9

Yapılması gereken birkaç iyileştirme var.

Kaydet() Metodu - soldan sağa kopyalama, kullanım EF bunun

yerine mantık inşa etmeyin:

:

myEmp.Employee_ID = emp.Employee_ID; 
myEmp.First_Name = emp.First_Name; 
myEmp.Middle_Name = emp.Middle_Name; 
myEmp.Last_Name = emp.Last_Name; 
myEmp.Supervisor_ID = emp.Supervisor_ID; 
myEmp.Active = emp.Active; 
myEmp.Is_Supervisor = emp.Is_Supervisor; 

Bunu yapabilirsin ctx.Employees.ApplyCurrentValues(emp).

Bu, grafikte aynı anahtara sahip bir varlık olup olmadığına bakar (FirstOrDefault() ile yeni aldığınızdan beri vardır) ve skaler değerleri geçtiğiniz varlıkla birlikte geçersiz kılar. ne yapıyorsun.

Yani 7 satırınız 1, artı herhangi bir skaler özellik eklerseniz - kodunuzu yeniden kodlamak zorunda kalmazsınız. Sadece hatırla - sadece skaler özellikler, seyir özellikleri için geçerlidir.

Neden birincil anahtar alımı için sorgu oluşturulsun?

var results = from item in ctx.Employees 
       where item.ID == emp.ID 
       select item; 

var myEmp = results.FirstOrDefault(); 

yapın:

var myEmp = ctx.Employees.WithId(emp.Id).SingleOrDefault(); 
:

var myEmp = ctx.Employees.SingleOrDefault(x => x.ID == emp.Id); 

Hatta daha da iyisi, bir boru/filtreyi tekniğini kullanmak Hemen Bunun yerine

SingleOrDefault() için yüklemi

WithId öğesinin nerede 01 olduğu Sağlanan çalışan kimliğine göre sorguyu filtreleyenuzantı yöntemi. Bu, filtreleme/iş mantığının deponuzdan/DAL'den ayrılmasını sağlar. Etki alanı modelinize gitmeli, böylece ORM'niz aracılığıyla alan varlıklarınızı sorgulamak için güzel bir akıcı API'ye sahip olabilirsiniz.

yöntemi ana anahtarla bir varlık alırken, şunları yapmalısınız daima kullanım SingleOrDefault() veya Single(), asla FirstOrDefault() veya First(). Birincil anahtarsa ​​- sadece bunlardan biri olmalıdır, bu yüzden birden fazla var ise bir istisna atmalısınız, bu da SingleOrDefault()'un yaptığı gibi. @Shiraz'ın da belirttiği gibi - FirstOrDefault()'unuz aşağıdaki sorguya çarpacaktır. <First/Single>OrDefault()'u kullandığınızda her zaman null denetimine ihtiyacınız vardır.

Get geliştirmenize aynı geliştirmeler yapılabilir.

Genel olarak, kodunuzda işlevsel olarak yanlış bir şey yoktur - yalnızca ince geliştirmeler, boş denetim ve istisna işlemlerine gereksinim duyar.

'u önerdiğim tek işlevsel iyileştirme, web hizmeti kodunuzu bir Genel Depoda yeniden düzenlemektir. Kod çok önemsiz ve herhangi bir varlık arasında yeniden kullanılabilir. Web servisi, işlemler, birincil anahtarlar veya EF mantığı ile ilgili olmamalıdır. EF DLL'ye bir referans bile içermemelidir. Bu mantığı bir arşivin arkasına saklayın ve kalıcı mantığı oraya bırakın (tabi ki bir arayüz aracılığıyla).

Yukarıda bahsettiğim değişiklikleri yaptıktan sonra, web hizmeti yöntemlerinizin her biri 5-7 satırdan daha fazla kod içermemelidir. Web hizmetinizde çok fazla istihbaratınız var - dilsiz ve inatçı cahil olmalıdır.

+1

"ApplyCurrentValues' +1" hakkında bir şey bilmiyordu! – Jeff

+0

ApplyCurrentValues ​​güvenlik sorunları için bir reçete gibi geliyor. Bu, GitHub'a isabet eden Toplu Uygulama hatası gibi görünüyor. –

+0

Sadece bir şey kullanmak için bağlam sarmak erişmek zorunda ApplyCurrentValues ​​http://stackoverflow.com/questions/14579590/cant-get-the-applycurrentvaluesentity-to-work-in-entity-framework-5 mutlu kodlama :) – ncubica

3

Ben genellikle denemek ve veri sözleşmesi doğrudan benim varlıkları kullanmak için oldukça kötü bir fikir olduğunu bulmak. Mümkün ve bazı durumlarda gayet iyi çalışıyor, ama her ne zaman nesne modelim biraz karmaşıklaşıyorsa, nesne grafiğiyle uğraşmak istemediğim şekilde endişelenmeye başladım.

Bunun yerine, ve bu istemciden bağımsızdır, ancak bir JS istemcisinde olduğu kadar uygulanabilir, veri sözleşmesi sınıflarını EF'de hiçbir eşleştirmeye sahip olmayan salt veri araçları (DTO) olarak düşünmeye çalışıyorum. Bu sınıflar, sadece ileri geri gönderdiğim belgeler, eğer istersen mesaj gövdesi. Benim modelimde komutları tercüme edebilirler veya bir sorguyu doldurmak için kullanılabilirler, ya da her neyse, ama bunlar kendilerinin değillerdir.

Bu, işleri önemli ölçüde basitleştiriyor. Basit bir hizmet ilk yazdığınızda daha fazla kod gibi görünebilir, ancak ömür boyu, işleri büyük ölçüde daha sürdürülebilir hale getirir.

Ve yan not olarak, sorumluluklarınızı biraz daha iyi bir şekilde ayırmayı da düşünmelisiniz. Web hizmeti sınıfı, veri bağlamının doğrudan elden çıkarılması sorumluluğuna sahip olmamalıdır; bu, sizin için tüm işleri halleden bir DAO'ya veya depo arabirimine (veya etki alanı hizmetine) bağlı olmalıdır (ve gerektiğinde işlemler uygular, vb.).

0

Get yönteminiz çökebilir.

bu hat boş dönerse

:
var emp = results.FirstOrDefault(); 

Daha sonra bu hat bir null başvuru özel kilitlenmesine: Ben de hataları günlüğü ile bazı try catch blokları koyardı

where item2.Employee_ID == emp.Employee_ID 

.