กรอบการทำงานหน่วยและพื้นที่เก็บข้อมูล | URF อย่างเป็นทางการ หน่วยงานที่ติดตามได้ และทีมโรงงานออกแบบ
เฟรมเวิร์กนี้ (ดาวน์โหลดทั้งหมดมากกว่า 100,000 ครั้ง) ช่วยลดพื้นที่ผิวของเทคโนโลยี ORM ของคุณไม่ให้เผยแพร่ในแอปพลิเคชันของคุณ เฟรมเวิร์กนี้ได้รับการออกแบบอย่างจงใจให้มีน้ำหนักเบา ขนาดเล็ก และไม่น่ากลัวที่จะขยายและบำรุงรักษา เมื่อเราพูดว่า Lightweight เราหมายถึงน้ำหนักเบาจริงๆ เมื่อใช้เฟรมเวิร์กนี้กับผู้ให้บริการ Entity Framework จะมีเพียง 10 คลาสเท่านั้น กรอบงานน้ำหนักเบานี้จะช่วยให้คุณจัดรูปแบบแอปพลิเคชันและระบบของคุณอย่างสวยงาม ไม่เกะกะ และง่ายดายด้วยพื้นที่เก็บข้อมูล หน่วยการทำงาน และการออกแบบที่ขับเคลื่อนด้วยโดเมน จะใช้ Generic Repositories หรือไม่? เฟรมเวิร์กนี้ให้อิสระทั้งสองที่เก็บข้อมูลทั่วไปและความสามารถในการเพิ่มวิธีการเก็บข้อมูลเฉพาะโดเมนของคุณเองหรือเรียกสั้น ๆ ว่า Unit of Work พร้อม Extensible และ Generic Repositories
การสาธิตสด: 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 ( ) ;
}
}
วิธีการทั้งหมดที่เปิดเผยจาก Repository<TEntity>
ใน Service<TEntity>
สามารถแทนที่ได้เพื่อเพิ่มโดเมนก่อนหรือหลัง/ตรรกะทางธุรกิจ ตรรกะทางธุรกิจของโดเมนควรอยู่ในชั้นบริการ และไม่ได้อยู่ในตัวควบคุมหรือพื้นที่เก็บข้อมูลเพื่อแยกข้อกังวล
ICustomerService
ซึ่งควรสืบทอด IService<TEnttiy>
เช่น IService<Customer>
เสมอCustomerService
ซึ่งใช้ ICustomerService
container.RegisterType<ICustomerService, CustomerService>()
ดูตัวอย่างถัดไปสำหรับรายละเอียดเพิ่มเติมเกี่ยวกับการเดินสาย 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<IDataContextAsync, NorthwindContext>(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 > ( ) ;
}
}