The Repository Pattern is a common construct to avoid duplication of data access logic throughout our application. This includes direct access to a database, ORM, WCF dataservices, xml files and so on. The sole purpose of the repository is to hide the nitty gritty details of accessing the data. We can easily query the repository for data objects, without having to know how to provide things like a connection string. The repository behaves like a freely available in-memory data collection to which we can add, delete and update objects.
The Repository pattern adds a separation layer between the data and domain layers of an application. It also makes the data access parts of an application better testable.
The example below show an interface of a generic repository of type T, which is a LINQ to SQL entity. It provides a basic interface with operations like Insert, Delete, GetById and GetAll. The SearchFor operation takes a lambda expression predicateto query for a specific entity.
using System;
using System.Linq;
using System.Linq.Expressions;
namespace Remondo.Database.Repositories
{
public interface IRepository<T>
{
void Insert(T entity);
void Delete(T entity);
IQueryable<T> SearchFor(Expression<Func<T, bool>> predicate);
IQueryable<T> GetAll();
T GetById(int id);
}
}
The implementation of the IRepository interface is pretty straight forward. In the constructor we retrieve the repository entity by calling the datacontext GetTable(of type T) method. The resulting Table(of type T) is the entity table we work with in the rest of the class methods. e.g. SearchFor() simply calls the Where operator on the table with the predicate provided.
using System;
using System.Data.Linq;
using System.Linq;
using System.Linq.Expressions;
namespace Remondo.Database.Repositories
{
public class Repository<T> : IRepository<T> where T : class, IEntity
{
protected Table<T> DataTable;
public Repository(DataContext dataContext)
{
DataTable = dataContext.GetTable<T>();
}
#region IRepository<T> Members
public void Insert(T entity)
{
DataTable.InsertOnSubmit(entity);
}
public void Delete(T entity)
{
DataTable.DeleteOnSubmit(entity);
}
public IQueryable<T> SearchFor(Expression<Func<T, bool>> predicate)
{
return DataTable.Where(predicate);
}
public IQueryable<T> GetAll()
{
return DataTable;
}
public T GetById(int id)
{
// Sidenote: the == operator throws NotSupported Exception!
// 'The Mapping of Interface Member is not supported'
// Use .Equals() instead
return DataTable.Single(e => e.ID.Equals(id));
}
#endregion
}
}
The generic GetById() method explicitly needs all our entities to implement the IEntity interface. This is because we need them to provide us with an Id property to make our generic search for a specific Id possible.
namespace Remondo.Database
{
public interface IEntity
{
int ID { get; }
}
}
Since we already have LINQ to SQL entities with an Id property, declaring the IEntity interface is sufficient. Since these are partial classes, they will not be overridden by LINQ to SQL code generation tools.
namespace Remondo.Database
{
partial class City : IEntity
{
}
partial class Hotel : IEntity
{
}
}
We are now ready to use the generic repository in an application.
using System;
using System.Collections.Generic;
using System.Linq;
using Remondo.Database;
using Remondo.Database.Repositories;
namespace LinqToSqlRepositoryConsole
{
internal class Program
{
private static void Main()
{
using (var dataContext = new HotelsDataContext())
{
var hotelRepository = new Repository<Hotel>(dataContext);
var cityRepository = new Repository<City>(dataContext);
City city = cityRepository
.SearchFor(c => c.Name.StartsWith("Ams"))
.Single();
IEnumerable<Hotel> orderedHotels = hotelRepository
.GetAll()
.Where(c => c.City.Equals(city))
.OrderBy(h => h.Name);
Console.WriteLine("* Hotels in {0} *", city.Name);
foreach (Hotel orderedHotel in orderedHotels)
{
Console.WriteLine(orderedHotel.Name);
}
Console.ReadKey();
}
}
}
}
Once we get of the generic path into more entity specific operations we can create an implementation for that entity based on the generic version. In the example below we construct a HotelRepository with an entity specific GetHotelsByCity() method. You get the idea.
using System.Data.Linq;
using System.Linq;
namespace Remondo.Database.Repositories
{
public class HotelRepository : Repository<Hotel>, IHotelRepository
{
public HotelRepository(DataContext dataContext)
: base(dataContext)
{
}
public IQueryable<Hotel> FindHotelsByCity(City city)
{
return DataTable.Where(h => h.City.Equals(city));
}
}
}
分享到:
相关推荐
在描述中提到的"Sample Repository Pattern with Unit of Work Example",意味着这个项目将展示如何在C#应用程序中实现这两种模式。Repository模式通常用来抽象数据存储,使得业务对象可以与具体的数据存储技术(如...
存储库是C#中存储库模式的通用实现。 它提供了一个存储库基类Repository<T> ,它公开了用于存储/检索数据的函数,还提供了一个对象上下文基类ObjectContext<T> ,一旦检索到数据,就可以对其进行操作。 它还公开了...
解决docker报错The push refers to a repository
Laravel开发-repository-pattern 用于生成Laravel存储库模式模块的Artisan命令界面
Ansys API example repository for demonstrating the use of REST and gRPC in different SW languages (Python, C++...)
cd example-repository-design-pattern 更新应用程序依赖项: composer install 将.env.example复制到.env并更新数据库配置 运行迁移: php artisan migrate migration 生成密钥: php artisan key:generate ...
The .NET Design Pattern Framework 4.5 is actually 10 products in one -- each filled with .NET code and information you will not find anywhere else -- and each working together, ready to give your apps...
在.NET Core开发中,Repository模式是一种常见的设计模式,它为应用程序提供了一种抽象的数据访问层。这个"10.1-Repository"项目很可能是为了演示或教学如何在.NET Core环境中实现这种模式。让我们深入探讨一下...
在.NET Core应用中,Entity Framework Core (EF Core) 是一个轻量级、高性能的对象关系映射(ORM)框架,它允许开发者用C#等语言直接操作数据库。依赖注入(Dependency Injection, DI)是一种设计模式,它有助于降低...
同时,通过提供的三个文件(The PCI ID Repository.txt、The PCI ID Repository_3.txt、The PCI ID Repository_2.txt),用户可以对比不同版本,查找最新的显卡信息。 总的来说,了解并利用"The PCI ID Repository ...
关于LaravelLaravel是一个具有表达力,优雅语法的Web应用程序框架。 我们认为,发展必须是一种令人愉快的,富有创造力的经历,才能真正实现。 Laravel通过减轻许多Web项目中使用的常见任务来减轻开发工作的痛苦,...
总结一下,使用官方 C# MongoDB 驱动程序创建 `MongoDbRepository` 是一种有效的方式,可以简化与 MongoDB 的交互,并提供了一种在 .NET 应用中组织数据访问层的结构化方法。通过这种方式,开发人员可以专注于业务...
MongoRepository是针对MongoDB数据库的一种实现,用于在C#环境中应用存储库模式。存储库模式是一种设计模式,它提供了一种抽象数据访问层的方式,使应用程序与数据存储机制解耦,提高了代码的可测试性和可维护性。在...
A work-in-progress repository for breaking the security of iOS 11.2 up to 11.2.6 .zip,A work-in-progress repository for breaking the security of iOS 11.2 up to 11.2.6
Repository_to_track_the_progress_in_Natural_Langua_NLP-progressLangua_NLP-progress.zip
PCI ID(显卡型号十六进制代码列表),linux下查看显卡型号,有时会返回十六进制代码,这个列表是The PCI ID Repository网站的列表,可以根据十六进制代码查询到相应显卡型号。 2.2版本,官方更新日期:2022-05-18 ...
斯坦福大学发布的"The Stanford 3D Scanning Repository"是一个广为人知的数据集,其中包含了一个著名的3D模型——斯坦福兔子。这个模型因其精确的细节和广泛的应用而被广大研究人员和开发者所采用,特别是在点云...
在本文中,重点是使用Python为SQLAlchemy创建一个通用存储库类,并在FastAPI项目中使用它。
repository