URF.NET
v5.1.0
작업 단위 및 저장소 프레임워크 | 공식 URF, 추적 가능한 개체 및 디자인 팩토리 팀
이 프레임워크(총 다운로드 수 10만 건 이상)는 ORM 기술이 애플리케이션에 전파되는 영역을 최소화합니다. 이 프레임워크는 가볍고, 설치 공간 크기가 작으며, 확장 및 유지 관리가 어렵지 않도록 의도적으로 설계되었습니다. 경량이라는 것은 실제로 경량을 의미합니다. Entity Framework 공급자와 함께 이 프레임워크를 사용할 때 클래스는 10개뿐입니다. 이 경량 프레임워크를 사용하면 리포지토리, 작업 단위 및 도메인 기반 설계를 통해 애플리케이션과 시스템을 우아하고 눈에 띄지 않게 쉽게 패턴화할 수 있습니다. 일반 저장소를 사용할 것인가 말 것인가? 프레임워크는 일반 저장소와 자신의 도메인별 저장소 메소드(간단히 확장 가능하고 일반 저장소가 있는 작업 단위) 를 추가하는 기능 모두의 자유를 허용합니다.
라이브 데모: longle.azurewebsites.net
public class CustomerController : ODataController { private readonly ICustomerService _customerService ; private readonly IUnitOfWorkAsync _unitOfWorkAsync ; public CustomerController ( IUnitOfWorkAsync unitOfWorkAsync , ICustomerService customerService ) { _unitOfWorkAsync = unitOfWorkAsync ; _customerService = customerService ; } // GET: odata/Customers [ HttpGet ] [ Queryable ] public IQueryable < Customer > GetCustomer ( ) { return _customerService . Queryable ( ) ; } // GET: odata/Customers(5) [ Queryable ] public SingleResult < Customer > GetCustomer ( [ FromODataUri ] string key ) { return SingleResult . Create ( _customerService . Queryable ( ) . Where ( t => t . CustomerID == key ) ) ; } // PUT: odata/Customers(5) public async Task < IHttpActionResult > Put ( string key , Customer customer ) { if ( ! ModelState . IsValid ) { return BadRequest ( ModelState ) ; } if ( key != customer . CustomerID ) { return BadRequest ( ) ; } customer . TrackingState = TrackingState . Modified ; _customerService . Update ( customer ) ; try { await _unitOfWorkAsync . SaveChangesAsync ( ) ; } catch ( DbUpdateConcurrencyException ) { if ( ! CustomerExists ( key ) ) { return NotFound ( ) ; } throw ; } return Updated ( customer ) ; } // POST: odata/Customers public async Task < IHttpActionResult > Post ( Customer customer ) { if ( ! ModelState . IsValid ) { return BadRequest ( ModelState ) ; } customer . TrackingState = TrackingState . Added ; _customerService . Insert ( customer ) ; try { await _unitOfWorkAsync . SaveChangesAsync ( ) ; } catch ( DbUpdateException ) { if ( CustomerExists ( customer . CustomerID ) ) { return Conflict ( ) ; } throw ; } return Created ( customer ) ; } //// PATCH: odata/Customers(5) [ AcceptVerbs ( " PATCH " , " MERGE " ) ] public async Task < IHttpActionResult > Patch ( [ FromODataUri ] string key , Delta < Customer > patch ) { if ( ! ModelState . IsValid ) { return BadRequest ( ModelState ) ; } Customer customer = await _customerService . FindAsync ( key ) ; if ( customer == null ) { return NotFound ( ) ; } patch . Patch ( customer ) ; customer . TrackingState = TrackingState . Modified ; try { await _unitOfWorkAsync . SaveChangesAsync ( ) ; } catch ( DbUpdateConcurrencyException ) { if ( ! CustomerExists ( key ) ) { return NotFound ( ) ; } throw ; } return Updated ( customer ) ; } // DELETE: odata/Customers(5) public async Task < IHttpActionResult > Delete ( string key ) { Customer customer = await _customerService . FindAsync ( key ) ; if ( customer == null ) { return NotFound ( ) ; } customer . TrackingState = TrackingState . Deleted ; _customerService . Delete ( customer ) ; await _unitOfWorkAsync . SaveChangesAsync ( ) ; return StatusCode ( HttpStatusCode . NoContent ) ; } // GET: odata/Customers(5)/CustomerDemographics [ Queryable ] public IQueryable < CustomerDemographic > GetCustomerDemographics ( [ FromODataUri ] string key ) { return _customerService . Queryable ( ) . Where ( m => m . CustomerID == key ) . SelectMany ( m => m . CustomerDemographics ) ; } // GET: odata/Customers(5)/Orders [ Queryable ] public IQueryable < Order > GetOrders ( [ FromODataUri ] string key ) { return _customerService . Queryable ( ) . Where ( m => m . CustomerID == key ) . SelectMany ( m => m . Orders ) ; } protected override void Dispose ( bool disposing ) { if ( disposing ) { _unitOfWorkAsync . Dispose ( ) ; } base . Dispose ( disposing ) ; } private bool CustomerExists ( string key ) { return _customerService . Query ( e => e . CustomerID == key ) . Select ( ) . Any ( ) ; } }
Service
의 Repository
에서 노출되는 모든 메서드를 재정의하여 사전 또는 사후 도메인/비즈니스 논리를 추가할 수 있습니다. 도메인 비즈니스 로직은 관심사 분리를 위해 컨트롤러나 저장소가 아닌 서비스 계층에 있어야 합니다.
IService
와 같이 항상 IService
상속해야 하는 ICustomerService
와 같은 인터페이스를 만듭니다.ICustomerService
구현하는 CustomerService
와 같은 인터페이스에 대한 구체적인 구현을 구현합니다.container.RegisterType()
. DI 및 IoC 연결에 대한 자세한 내용은 다음 예를 참조하세요. public interface ICustomerService : IService < Customer >
{
decimal CustomerOrderTotalByYear ( string customerId , int year ) ;
IEnumerable < Customer > CustomersByCompany ( string companyName ) ;
IEnumerable < CustomerOrder > GetCustomerOrder ( string country ) ;
}
public class CustomerService : Service < Customer > , ICustomerService
{
private readonly IRepositoryAsync < Customer > _repository ;
public CustomerService ( IRepositoryAsync < Customer > repository ) : base ( repository )
{
_repository = repository ;
}
public decimal CustomerOrderTotalByYear ( string customerId , int year )
{
// add any domain logic here
return _repository . GetCustomerOrderTotalByYear ( customerId , year ) ;
}
public IEnumerable < Customer > CustomersByCompany ( string companyName )
{
// add any domain logic here
return _repository . CustomersByCompany ( companyName ) ;
}
public IEnumerable < CustomerOrder > GetCustomerOrder ( string country )
{
// add any domain logic here
return _repository . GetCustomerOrder ( country ) ;
}
public override void Insert ( Customer entity )
{
// e.g. add any business logic here before inserting
base . Insert ( entity ) ;
}
public override void Delete ( object id )
{
// e.g. add business logic here before deleting
base . Delete ( id ) ;
}
}
UnityConfig.cs
public class UnityConfig
{
private static Lazy < IUnityContainer > container = new Lazy < IUnityContainer > ( ( ) =>
{
var container = new UnityContainer ( ) ;
RegisterTypes ( container ) ;
return container ;
} ) ;
public static IUnityContainer GetConfiguredContainer ( )
{
return container . Value ;
}
public static void RegisterTypes ( IUnityContainer container )
{
container
// Register DbContext instead of IDataDataContext, which is now obsolete.
//.RegisterType(new PerRequestLifetimeManager())
. RegisterType < DbContext , NorthwindContext > ( new PerRequestLifetimeManager ( ) )
. RegisterType < IUnitOfWorkAsync , UnitOfWork > ( new PerRequestLifetimeManager ( ) )
. RegisterType < IRepositoryAsync < Customer > , Repository < Customer > > ( )
. RegisterType < IRepositoryAsync < Product > , Repository < Product > > ( )
. RegisterType < IProductService , ProductService > ( )
. RegisterType < ICustomerService , CustomerService > ( )
. RegisterType < INorthwindStoredProcedures , NorthwindContext > ( new PerRequestLifetimeManager ( ) )
. RegisterType < IStoredProcedureService , StoredProcedureService > ( ) ;
}
}