2016-10-17 9 views
0

데이터베이스에 액세스 할 때 다른 레이어를 추가하여 .NET 프로젝트를 개선하고 싶습니다. 나는 매우 직접적인 꽤 많은 데이터베이스에 액세스하고 있습니다.net에서 데이터 액세스 레이어 모범 사례 구현 프로젝트 MVC

public class DataAccess 
{  
public bool checkIfExists(String Id) 
    { 
     try 
     { 
      SqlConnection cnn = new SqlConnection(dataConnection); 
      cnn.Open(); 
      SqlCommand check_Id = new SqlCommand("SELECT COUNT(*) FROM TABLE_GUID WHERE ([USER_ID] = @Id)", cnn); 
      check_Id.Parameters.AddWithValue("@Id", Id); 
      int UserExist = (int)check_Id.ExecuteScalar(); 

      if (UserExist > 0) 
      { 
       return true; 
      } 
      else 
      { 
       return false; 
      } 
     } 
     catch (SqlException ex) 
     { 
      Debug.WriteLine("SQL Exception " + ex); 
      DisplaySqlErrors(ex); 
      throw ex; 
     } 
    } 
} 

public class AgentBeanController : Controller 
{ 
    // GET: AgentBean 
    public ActionResult Index(string name) 
    { 
     return View(); 
    } 

    [AllowAnonymous] 
    [WebMethod]    
    public string AgentURL() //here we create Agent URL and return it to the view 
    { 
     string var = Models.AgentBean.createGUID("TODO");    
     return var;   
    } 


} 

: 나는 "도우미"라는 별도의 폴더에 DATAACCESS 클래스를 배치하고

namespace Company.Models 
{ 
public static class AgencyBean 
{ 
[WebMethod] 
    [ScriptMethod(UseHttpGet = true)] 
    public static String createGUID(string name) 
    { 
     DataAccess dataAccess = new DataAccess(); 
     bool exists = dataAccess.checkIfExists(Id); 
     if(exist) 
     { 
      dataAccess.delete(Id); 
     } 
     retur "ok"; 
    } 
} 
} 

내 쿼리의 대부분을 포함 : 이것은 내 코드입니다 방법. 어떻게하면 더 나은 기술이 될 수 있습니까? 그렇다면이 액세스는 서비스 계층을 통한 액세스와 같이 더욱 안전 할 수 있습니다. 일부 서버에서는 기존 SQL 데이터베이스에 연결하고 프로젝트에서는 MVC 아키텍처로 작업하고 있습니다.

+1

올바른 길을 가고 있습니다.Google에 "데이터 저장소"및 "종속성 삽입"이라는 용어를 사용하면 한 걸음 더 나아갈 수 있습니다. 저장소의 일반적인 개념은 모델 계층에서 데이터에 액세스하기 위해 별도의 클래스를 사용하지만 (지금처럼) 인터페이스를 준수한다는 것입니다. AgencyBean 클래스를 인스턴스화하면 해당 인터페이스를 구현하는 객체를 인수로 사용하게됩니다. 이점은 단위 테스트에만 사용되는 데이터베이스를 다루지 않는 인터페이스의 두 번째 구현을 가질 수 있다는 것입니다. Ninject와 같은 DI 도구를 사용하면 코드를 더 쉽게 작성할 수 있습니다. –

+0

이제는 단위 테스트를 구현하기를 원하며 DI가 필요하다는 것을 알았습니다. 조언 주셔서 감사합니다! –

답변

1

그래서 여기에 내가 과거에 한 일이 있습니다.

먼저 모델이 네임 스페이스 ... 모델에 데이터베이스 연결이 없어야합니다. 대신 컨트롤러와 같은 별도의 클래스를 사용하여 일부 모델을 수분있게 만듭니다.

둘째, "저장소"클래스에 연결되는 "서비스"클래스를 사용했습니다. 저장소 클래스는 사용중인 데이터베이스의 정확한 "유형"을 식별하기위한 인터페이스를 구현합니다. 그러나 이것이 요구 사항의 일부가 아니라면 그렇게 할 필요가 없을 것입니다.

셋째, 의존성 주입 (DI)을 참조하십시오. 거기에 몇 가지 프레임 워크가 있습니다. 개인적으로 저는 Autofac을 사용해 왔지만, 다른 사람들도 작업을 더 쉽게하기 위해 존재합니다.

넷째, "컨트롤러", "서비스"및 "리포지토리"클래스에서 종속성 삽입과 계약을 구성하는 데 필요한 모든 인터페이스를 구현하십시오.

다섯째, 실제 컨트롤러 네임 스페이스를 사용하고 http 네임 스페이스에서 HTTP 호출을 앞뒤로 밀고 나가는 작업을하지 않을 것입니다. 대신 컨트롤러 클래스에서 작업을 만들고 인스턴스를 인스턴스화하십시오. "agencyBean"을 사용하여 데이터로 수분을 공급하고 해당 모델을 사용자가 볼 수 있도록 반환하십시오.

기본적으로 이와 같은 시나리오에서는 각 구성 요소가 지시 한대로 유지하면서 책임을 작은 부분으로 나누고 그에 초점을 맞추기 위해 노력하고 있습니다. 컨트롤러는 모델을 "가져와야"하고 필요한 경우 또는 다른 비즈니스 유형 논리로 변환을 수행해야합니다.
서비스가 컨트롤러와 데이터베이스 계층 간의 통신을 처리해야합니다.
데이터 액세스 레이어 (즉,이 경우 일부 리포지토리 클래스)는 모든 새 데이터 연결을 수행하거나 저장 프로 시저 또는 쿼리에 대한 호출을 설정합니다.

이런 식으로 일하는 것은 많은 이점이 있습니다. 큰 것들 중 일부는 유지 보수성, 가독성, 코드 재사용입니다. 물론 그것은 프로젝트가 파일을 어디에 있든 조금 더 복잡하게 만든다. 그러나 그것은 좋은 일이 될 수있다. 모든 것을 하나의 클래스로 슬래 밍하고 모든 것을 처리하는 것보다 훨씬 낫습니다.

그러나 FYI는 지난 구현에서 나온 것입니다 ... 더 나은 방법이있을 것입니다. 이 설정은 저의 팀과 제가 잘 해냈습니다.

게시 한 코드 중 일부를 사용하는 작은 예제가 있습니다. 오타가 있는지 이것을 확인하지 않았지만 컴파일되지 않았지만 내가 말하는 것에 대해 일반적인 생각을 제공해야합니다 ....

namespace Company.Models 
{ 
    public class AgencyBean 
    { 
     public AgencyName{get;set;} 
     public AgencyId{get;set;} 
     // other properties... 
    } 
} 




namespace Company.Controllers 
{ 
    public class MyController : Controller 
    { 
     private readonly IMyService myService; 


     public MyController(IMyService myService) // <-- this is your dependency injection here... 
     { 
      this.myService = myService; 
     } 

     [WebMethod] 
     [ScriptMethod(UseHttpGet = true)] 
     public static String createGUID(string name) 
     { 
      var model = new AgencyBean(); 
      model.AgencyId = 1; 
      model = myService.getAgency(agencyBean);    
      return model; 
     } 
    } 
} 




namespace Company.Services 
{ 
    public class MyService 
    { 
     private readonly IMyRepository myRepository; 


     public MyService(IMyRepository myRepository) // <-- this is your dependency injection here... 
     { 
      this.myRepository = myRepository; 
     } 

     public AgencyBean getAgency(AgencyBean model){ 
      var dataTable = myRepository.getAgencyData(model.AgencyId); 
      // fill other properties of your model you have... 
      // ... 
      // ... 
      return model; 
     } 
    } 
} 



namespace Company.Repositories 
{ 
    public class MyRepository : IDatabaseCommon // <-- some interface you would use to ensure that all repo type objects get connection strings or run other necessary database-like setup methods... 
    { 
     private readonly String connectionString{get;set;} 

     public MyRepository() 
     { 
      this.connectionString = //get your connection string from web.config or somewhere else...; 
     } 

     public DataTable getAgencyData(int id){ 
      var dataTable = new DataTable(); 

      // perform data access and fill up a data table 

      return dataTable; 
     } 
    } 
} 
+0

저는 비즈니스 로직이 모델에 있어야하고 컨트롤러가 가능한 한 단순해야한다고 읽었습니다. 그래서 내가 이런 식으로 코딩을 시작했습니다. 그런 다음 사람들이 저를 지적한 것처럼 서비스 계층을 권장하는 비슷한 게시물을 발견했습니다. 그래서, 당신의 예제에서 IMyservice 내 쿼리를 포함하는 새로운 파일에있는 인터페이스, 맞죠? 나는이 MVC 패턴을 "해독"하고 싶지 않기 때문에 특정 파일을 어디에서 찾을 지 혼란 스럽다. –

+1

IMyService는 다른 파일에서 작성하는 인터페이스이다. 그러나 그것은 당신이 당신의 질문을 쓰는 곳이 아니라 당신이 쓰지 않는 곳이 아닙니다. 한 무리의 SQL 명령을 쓰고 싶다면 "QueryModel"과 같은 다른 "모델"클래스를 권하고 SQL 문자열을 반환하는 상수 일 것입니다. 그러나 실제로, 나는 개인적으로 그렇게하지 않습니다. 오히려 데이터베이스 수준에서 저장 프로 시저/함수를 사용하고 응용 프로그램 코드에서 해당 함수를 호출합니다. db에 저장된 procs/함수에는 모든 SQL이 포함됩니다. – dvsoukup

+0

이제 당신의 주장이 드러났습니다. 모델을 매개 변수로 보내고 DI를 사용하여 myRepository를 사용하여 MyService에 채운 다음 모델을 반환합니다. 한가지 더 질문합니다. Unity DI를 Nugget에서 설치했지만 parameterless 오류가 발생했습니다. 수동으로 Application_Start()에 수동으로 추가해야합니까, 아니면 설치 프로그램에서 추가해야 할 사항입니까? –