我正在使用业务对象(员工、产品)创建一个新项目。由于限制,我没有使用 LINQ to SQL 或任何 ORM 映射器。
我必须手动编写数据访问层代码。我有兴趣使用“存储库模式”。
根据我的理解,我必须创建一个通用存储库 IRepository,它由所有存储库 ProductRepository、EmployeeRepository 实现。
让我困惑的是不同的业务对象有不同的需求。例如:
产品库
GetAllProducts ();
GetProductById (int id);
GetProductByMaxPrice (double price);
GetProductByNamePrice (string name, double Price);
Get... (...);
员工资料库
GetEmployeeByAge ();
GetEmployeeByJob (string description);
GetEmployeeBySalary (double salary);
Get... (...); //and so on
如何创建满足不同对象的不同数据访问要求的通用存储库?
我已经阅读了很多关于 Repository Pattern 的理论,但非常希望能有一个有效的例子。
此外,如果我可以使用通用存储库创建所有存储库,那么使用工厂模式也会变得容易。例如:
interface IRepository
{
....
}
ProductRepository : IRepository
{
....
}
EmployeeRepository : IRepository
{
....
}
然后我们可以有效地使用工厂模式:
IRepository repository;
repository = new ProductRepository ();
repository.Call_Product_Methods ();
repository = new EmployeeRepository ();
repository.Call_Employee_Methods ();
最佳答案
repository Pattern 是一个很好用的模式,但如果没有正确使用它,不但不会让你的生活更轻松,反而会带来巨大的痛苦!
因此,执行此操作的最佳方法(因为您不想使用 EF 或其他 ORM)是创建通用接口(interface),然后创建基本抽象实现。这样您就不需要为每个存储库编写代码,您只需按类型实例化它们即可!
在此之后,如果您有特定于某些实体的任何特定方法,您都可以从存储库继承并根据需要覆盖或添加方法和属性。
如果你想使用 Repository Pattern,我也建议你使用 IUnitOfWork 模式,并将它与 repository 分开。
两个界面应该是这样的:
非常简单的 IUnitOfWork:
Public interface IUnitOfWork
{
bool Save();
}
还有他们,Repository 接口(interface),使用泛型:
public interface IRepository<TEntity> : IDisposable where TEntity : class
IUnitOfWork Session { get;}
IList<TEntity> GetAll();
IList<TEntity> GetAll(string[] include);
IList<TEntity> GetAll(Expression<Func<TEntity, bool>> predicate);
bool Add(TEntity entity);
bool Delete(TEntity entity);
bool Update(TEntity entity);
bool IsValid(TEntity entity);
}
方法 .Add()、.Delete() 不应将任何内容发送到数据库,但它们应始终将更改发送到 IUnitOfWork(您可以在 DAL 类中实现),并且仅当您调用 . IUnitOfWork 的 Save() 方法,您会将内容保存到数据库。
我已经使用 EntityFramework 实现了我的 Repository 类,这使事情变得更容易,但您可以按照自己的方式进行。
您将使用的代码如下所示:
void SomeMethod()
{
using (IUnitOfWork session = new YourUnitOfWorkImplementation())
{
using (var rep = new Repository<Client>(session))
{
var client1 = new Client("Bob");
var client2 = new Cliente("John");
rep.Add(client1);
rep.Add(client2);
var clientToDelete = rep.GetAll(c=> c.Name == "Frank").FirstOrDefaut();
rep.Delete(clientToDelete);
//Now persist the changes to the database
session.Save();
{
{
}
就像我说的,有了 EF 和 DbContext,这就容易多了,下面是我的 Repository 类的一小部分:
public class Repository : Component, IRepository
{
protected DbContext session;
{
get
{
if (session == null)
throw new InvalidOperationException("A session IUnitOfWork do repositório não está instanciada.");
return (session as IUnitOfWork);
}
}
public virtual DbContext Context
{
get
{
return session;
}
}
public Repository()
: base()
{
}
public Repository(DbContext instance)
: this(instance as IUnitOfWork)
{
#endregion
public IList<TEntity> GetAll<TEntity>() where TEntity : class
{
return session.Set<TEntity>().ToList();
}
public bool Add<TEntity>(TEntity entity) where TEntity : class
{
if (!IsValid(entity))
return false;
try
{
session.Set(typeof(TEntity)).Add(entity);
return session.Entry(entity).GetValidationResult().IsValid;
}
catch (Exception ex)
{
if (ex.InnerException != null)
throw new Exception(ex.InnerException.Message, ex);
throw new Exception(ex.Message, ex);
}
} ...
这样您就不需要构建 GetEmployeeByAge,您只需编写:
IEnumerable<Employee> GetEmployee(int age)
{
return rep.GetAll<Employee>(e=> e.Age == age);
}
或者你可以直接调用(不需要创建方法)
关于c# - 具有数据访问层的通用存储库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16572743/
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah
我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以
有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha
我正在使用Rails3.1并在一个论坛上工作。我有一个名为Topic的模型,每个模型都有许多Post。当用户创建新主题时,他们也应该创建第一个Post。但是,我不确定如何以相同的形式执行此操作。这是我的代码:classTopic:destroyaccepts_nested_attributes_for:postsvalidates_presence_of:titleendclassPost...但这似乎不起作用。有什么想法吗?谢谢! 最佳答案 @Pablo的回答似乎有你需要的一切。但更具体地说...首先改变你View中的这一行对此#
我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_