Unit-of-Work & Repository Framework | Official URF, Trackable Entities & Design Factory Team
This framework (over 100K+ total downloads) minimizes the surface area of your ORM technology from disseminating in your application. This framework was deliberately designed to be lightweight, small in footprint size, and non-intimidating to extend and maintain. When we say lightweight we really mean lightweight, when using this framework with the Entity Framework provider there are only 10 classes. This lightweight framework will allow you to elegantly, unobtrusively, and easily patternize your applications and systems with Repository, Unit of Work, and Domain Driven Design. To use Generic Repositories or not? The framework allows the freedom of both, generic repositories and the ability to add in your own domain specific repository methods, in short Unit of Work with extensible and generic Repositories.
Live demo: 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();
}
}
All methods that are exposed from Repository<TEntity>
in Service<TEntity>
are overridable to add any pre or post domain/business logic. Domain business logic should be in the Service layer and not in Controllers or Repositories for separation of concerns.
ICustomerService
, which should always inherit IService<TEnttiy>
e.g. IService<Customer>
CustomerService
which implements ICustomerService
container.RegisterType<ICustomerService, CustomerService>()
, see next example for more details on wiring up 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);
}
}
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>();
}
}
注:c#初学者,懂得不是很多,因为最近有一个项目才开始研究的,学术不精,勿喷。 这里我们用的是明华URF-R330读写器 卡片类型M1 开发环境vs2008 由于我只需要进行对卡片的读取和修改,所以这篇文章只针对读卡写卡而生 首先我们得简单的了解一下读卡器从连接电脑到读取卡片到写卡这一个简单的过程 : 1.读卡器连接电脑,明华这款读卡器是利用USB接口的,首先是驱动吗?这个大家都懂(这里我是没有用
在对接api时候,经常需要对字符串进行各种编码处理,系统可能是异构的,实现语言也就可能是不一样的。所以经常会使人犯一些2B的错误! 比如:php实现的api中用了rawurlencode,文档中写,需要对字符串进行urlencode编码,.net的开发人员看到文档,直接使用HttpUtitlity.UrlEncode, 本以为问题已经解决,实际埋下了一个大坑! 其实php的rawur
项目目标部署环境:CentOS 7+ 项目技术点:.netcore2.0 + Autofac +webAPI + NHibernate5.1 + mysql5.6 + nginx 开源地址:https://github.com/wmowm/nh.core 很多小伙伴,初识.net core都不知道如何下手,从哪里开始学习,这让我想起群里经常有小伙伴问,mvc怎么学习? 我觉得,第一步应该找到一个
我创建了一个,其中包含一个自定义。在整个应用程序中使用时,不能直接访问控件,因为它在逻辑上嵌入在中。 因此,为了访问的项,我在返回ToolStrip项的类中定义了一个属性。 现在,可以通过使用属性以编程方式编辑的项,但在设计模式下不能这样做。 就像有人将从拖动到窗体,转到,选择项的属性并相应地操作嵌入的的项;正如我们在items的帮助下使用任何标准控件的items集合一样。 在此,尽管的属性显示在
问题内容: 假设有一个包含以下表的数据库: 带customer_ID(键字段),customer_name的customer_table 带order_ID(键字段),customer_ID,product_ID的orders_table 现在,假设我想查找订购了10种以上不同类型产品的所有客户的名称,以及订购的产品类型的数量。同一产品的多个订单不计算在内。 我认为下面的查询应该可以,但是有以下问
问题内容: 我有一个Oracle 11g XE数据库,并且有一个查询结果集: 我想在逗号分隔的同一行中获得所有相关类别的不同ID,像这样 我以前使用过Postgres,并在那里提供了帮助。如何在Oracle 11g XE中获得相同的结果? 问题答案: 除非您在存储过程中使用它来将输出另存为数组(或集合),否则使用的查询应该足够并提供相同的输出。 在oracle中,我们没有像这样的简单转换函数。但是
问题内容: 我有正在用JSP开发的应用程序,我希望以XLS(MS Excel格式)从数据库中导出一些数据。 在tomcat下,是否可以像正常的Java应用程序一样编写文件,然后生成指向该文件的链接?还是我需要使用特定的API? 这样做会不会有权限问题? 问题答案: 尽管您可以使用像JExcelAPI这样的功能强大的库,但是只要您将响应的MIME类型设置为“ application / vnd.ms
问题内容: 检索适用于所有浏览器的XmlHttpRequest对象的最简单,最安全的方法是什么?没有任何额外的库。您是否经常使用一个代码段? PS:我知道网上有很多例子,但这恰恰是我要问的原因:例子太多了,我只想简单实用的东西来工作。 问题答案: 虽然我建议使用完整的库来简化用法,但是在现代浏览器中,进行AJAX请求可能非常简单: 以下代码段是基于quirksmode.org的代码段的更高级代码段
问题内容: 我在SQL Server的更大的Select语句中有以下查询: 在某些条目(例如)之后,此列将生成一些奇怪的符号。我不知道这是哪里来的。我尝试`SELECT SelectedComments FROM 问题答案: 如果您修改了For Xml Path的用法,它将为您完成转义操作,并且您无需诉诸使用Replace函数:
问题内容: 在我的项目中,每次打开JSP时都要分配一个变量。我在JSP和EL 中用scriptlet尝试过,它可以返回变量。 但似乎不起作用。 之后出现错误,是否无法在scriptlet中直接从EL分配变量? 问题答案: 您正在混合 脚本 和EL,并期望它们“同步”运行。那只是行不通的。一个是写的JSP的旧校园的方式 和另一种是写的JSP的现代生活方式。您应该同时使用一个或多个。 回到具体的问题,
问题内容: 简而言之; 我在XML文件中生成了许多空行,并且我正在寻找一种删除它们的方法,以作为倾斜文件的一种方法。我怎样才能做到这一点 ? 详细说明;我目前有这个XML文件: 我使用此Java代码删除所有标签,并添加新标签: 在多次执行此方法后,我得到了一个XML文件,其结果正确,但是在“ paths”标记之后和第一个“ path”标记之前有许多空行,如下所示: 有人知道该如何解决吗? ----