2011-02-14 5 views
10

이것은 매우 모호하고 주관적인 질문입니다. 나는이/ajax 호출을 사용하여 브라우저에서 데이터를 보내거나 검색하는 가장 좋은 방법인지 알고 싶습니다. 백엔드 webservice에서 엔티티 프레임 워크를 사용하고 싶습니다. 다음은 두 가지 예제 함수입니다.엔티티 프레임 워크와 자바 스크립트 상호 작용을 향상시키는 방법

"최상의"기준은 코드 작성, 읽기 가능한 코드 및 강력한 아키텍처의 속도입니다.

의견 및 제안 및 의견을 보내 주셔서 감사합니다.

가져 오기 기능

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

저장 기능

[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

왜 'AjaxEmployee' 클래스가 별도입니까? 그것은 당신의'Employee' 엔터티의 투사입니까? –

+0

별도의 클래스는 자바 스크립트로 보낼 때 JSON에 더 잘 serialize하는 것입니다.Employee와 Time_Off 레코드 사이에는 관계가 있기 때문에 http://mytechworld.officeacuity.com/?p=577 – Sam

답변

9

몇 가지 개선 사항이 있습니다.

저장() 방법 - 왼쪽에서 오른쪽으로 복사, 사용 EF이의

대신 로직에 내장하지 마십시오 :

:

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; 

당신은이 작업을 수행 할 수 있습니다 ctx.Employees.ApplyCurrentValues(emp).

그래프에서 동일한 키를 가진 엔티티를 찾고 (방금 FirstOrDefault()으로 검색했기 때문에), 전달하는 엔티티로 스칼라 값을 무시합니다. 정확히 일치합니다 네가하는 일.

여분의 스칼라 속성을 추가하면 7 줄이 더해 지므로 코드를 리팩터링 할 필요가 없습니다. 기억하십시오. 스칼라 속성에 대해서만 작동하며 네비게이션 속성은이 아닙니다.

왜 기본 키 검색을위한 쿼리를 작성합니까?

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

var myEmp = results.FirstOrDefault(); 

이 수행합니다 :

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

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

또는 더 나은을하는 파이프/필터를 기술을 사용 그냥이 대신

SingleOrDefault()에 술어를 사용

여기서 WithId은 01입니다.확장 메소드는 제공된 직원 ID를 기반으로 쿼리를 필터링합니다. 이렇게하면 필터링/비즈니스 로직을 저장소/DAL에서 분리 할 수 ​​있습니다. 도메인 모델에 있어야하므로 ORM을 통해 도메인 엔터티를 쿼리 할 수있는 유창한 API를 사용할 수 있습니다.

당신은 기본 키를 통해 개체를 검색 할 때, 당신이해야 항상 사용 SingleOrDefault() 또는 Single(), 결코 FirstOrDefault() 또는 First(). 기본 키인 경우 하나만 있어야하므로 하나 이상 존재하는 경우 예외를 throw해야합니다 (즉 SingleOrDefault()의 경우). 그리고 @Shiraz 언급 - 귀하의 FirstOrDefault() 아래 쿼리가 충돌합니다. <First/Single>OrDefault()을 사용할 때 항상 널 확인이 필요합니다.

Get 메서드를 동일한 방식으로 향상시킬 수 있습니다.

전체적으로 코드에는 기능상 오류가 없습니다. 단지 미세한 개선, Null 검사 및 예외 처리가 필요합니다.

유일한 기능 향상 나는 매우가 귀하의 웹 서비스 코드를 일반 저장소로 리팩토 할 것을 권장합니다. 코드는 매우 사소하기 때문에 어떤 엔티티에서나 재사용 할 수 있습니다. 웹 서비스는 트랜잭션, 기본 키 또는 EF 논리와 관련되어서는 안됩니다. EF DLL에 대한 참조가 없어야합니다. 이 논리를 저장소 뒤에 캡슐화하고 지속성 논리를 거기에 위임합니다 (물론 인터페이스를 통해).

위에서 언급 한 변경 사항을 적용한 후에는 웹 서비스 메소드의 코드 수가 5 ~ 7 줄을 넘지 않아야합니다.

웹 서비스에 지능이 너무 많습니다. 무의미하고 지속적으로 무지해야합니다.

+1

에 따라 직렬화가 제대로 수행되지 않습니다. 'ApplyCurrentValues' +1에 대해 전혀 알지 못했습니다. – Jeff

+0

ApplyCurrentValues는 보안 문제를 해결하는 방법처럼 들립니다. 이것은 GitHub에 충돌 한 Mass Apply 버그와 같습니다. –

+0

사용하기 위해 컨텍스트 랩에 액세스해야하는 한 가지. ApplyCurrentValues ​​http://stackoverflow.com/questions/14579590/cant-get-the-applycurrentvaluesentity-to-work-in-entity-framework-5 해피 코딩 :) – ncubica

3

나는 그것이 일반적으로 시도하고 데이터 계약에 직접 내 엔티티를 사용하는 아주 나쁜 생각 것을 찾을 수 있습니다. 어떤 경우에는 가능하고 잘 작동하지만, 객체 모델이 조금 복잡해지면 객체 그래프에 대해 걱정할 필요가없는 방식으로 객체 그래프를 걱정하기 시작합니다.

대신 클라이언트에 관계없이 JS 클라이언트에도 적용 할 수 있습니다. 데이터 계약 클래스를 EF에서 매핑이없는 순수 데이터 트럭 (DTO)으로 생각해 봅니다. 그 클래스들은 내가 앞뒤로 지나가는 문서 일 뿐이다. 내 모델의 명령으로 변환되거나 쿼리를 채우는 데 사용될 수도 있지만 그 자체는 엔터티 자체가 아닙니다.

이것은 많은 것들을 단순화합니다. 평범한 서비스를 처음 작성할 때 코드가 더 많이 느껴질 수도 있지만 평생 동안 많은 것을 유지 관리 할 수 ​​있습니다.

부수적으로, 책임을 좀더 나누는 것도 고려해야합니다. 웹 서비스 클래스는 데이터 컨텍스트를 직접 처리하는 책임을 가져서는 안되며 DAO 또는 저장소 인터페이스 (또는 도메인 서비스)에 의존해야합니다 (또는 필요한 경우 트랜잭션 적용 등).

0

get 메소드가 중단 될 수 있습니다.

이 행이 null을 반환하는 경우

:
var emp = results.FirstOrDefault(); 

다음이 라인은 null 참조 예외와 충돌합니다 : 나는 또한 오류 로깅 일부 시도의 catch 블록에 넣어 것

where item2.Employee_ID == emp.Employee_ID 

.

관련 문제