我一直在寻找一个很好的解决方案来解决典型的Repository模式所带来的问题(专门的查询方法的增长列表等等.请参阅:http://ayende.com/blog/3955/repository-是新单身人士).
我非常喜欢使用Command查询的想法,特别是通过使用规范模式.但是,我的规范问题是它只涉及简单选择的标准(基本上是where子句),而不涉及查询的其他问题,例如连接,分组,子集选择或投影等.基本上,许多查询必须通过所有额外的箍来获得正确的数据集.
(注意:我在命令模式中使用术语"命令",也称为查询对象.我不是在命令/查询分离中讨论命令,其中查询和命令之间存在区别(更新,删除,插入))
因此,我正在寻找封装整个查询的替代方案,但仍然足够灵活,以至于您不仅仅需要交换spaghetti Repositories以进行大量的命令类.
我已经使用过,例如Linqspecs,虽然我发现能够为选择标准指定有意义的名称有一些价值,但这还不够.也许我正在寻找一种结合多种方法的混合解决方案.
我正在寻找其他人可能已经开发的解决方案,以解决这个问题,或解决不同的问题,但仍满足这些要求.在链接的文章中,Ayende建议直接使用nHibernate上下文,但我觉得这很大程度上使您的业务层复杂化,因为它现在还必须包含查询信息.
等待期过后,我会在此提供赏金.因此,请提供有价值的解决方案,并提供良好的解释,我将选择最佳解决方案,并向选手投票.
注意:我正在寻找基于ORM的东西.不必明确是EF或nHibernate,但这些是最常见的并且最适合.如果它可以很容易地适应其他ORM,那将是一个奖励.Linq兼容也不错.
更新:我真的很惊讶这里没有很多好的建议.似乎人们完全是CQRS,或者他们完全在资源库中.我的大多数应用程序都不够复杂,无法保证CQRS(大多数CQRS倡导者都会说你不应该使用它).
更新:这里似乎有点混乱.我不是在寻找新的数据访问技术,而是在业务和数据之间设计合理的界面.
理想情况下,我正在寻找的是Query对象,规范模式和存储库之间的某种交叉.正如我上面所说,规范模式只处理where子句方面,而不是查询的其他方面,如连接,子选择等.存储库处理整个查询,但一段时间后失控.查询对象也处理整个查询,但我不想简单地用查询对象的爆炸替换存储库.
我看到这个代码使用LINQ to SQL,但是当我使用Entity Framework时,它会抛出此错误:
LINQ to Entities无法识别方法'System.Linq.IQueryable'1 [MyProject.Models.CommunityFeatures] GetCommunityFeatures()'方法,并且此方法无法转换为商店表达式.
存储库代码是这样的:
public IQueryable<Models.Estate> GetEstates()
{
return from e in entity.Estates
let AllCommFeat = GetCommunityFeatures()
let AllHomeFeat = GetHomeFeatures()
select new Models.Estate
{
EstateId = e.EstateId,
AllHomeFeatures = new LazyList<HomeFeatures>(AllHomeFeat),
AllCommunityFeatures = new LazyList<CommunityFeatures>(AllCommFeat)
};
}
public IQueryable<Models.CommunityFeatures> GetCommunityFeatures()
{
return from f in entity.CommunityFeatures
select new CommunityFeatures
{
Name = f.CommunityFeature1,
CommunityFeatureId = f.CommunityFeatureId
};
}
public IQueryable<Models.HomeFeatures> GetHomeFeatures()
{
return from f in entity.HomeFeatures
select new HomeFeatures()
{
Name = …Run Code Online (Sandbox Code Playgroud) 我想知道我应该如何分组我的存储库?就像我在asp.net mvc和我的书中看到的例子一样,他们基本上每个数据库表使用一个存储库.但是,这似乎是很多存储库导致您必须稍后调用许多存储库来进行模拟和填充.
所以我猜我应该把它们分组.但是我不确定如何将它们分组.
现在我做了一个注册存储库来处理我的所有注册内容.然而,在我有3个存储库来执行此操作之前,我需要更新4个表.
例如,其中一个表是许可证表.当他们注册时,我查看他们的密钥并检查它是否存在于数据库中.现在如果我需要在注册之外的其他位置检查此许可证密钥或该表中的其他内容会发生什么?
一个点可能是登录(检查密钥是否未过期).
那么在这种情况下我该怎么做?再次重写代码(打破DRY)?尝试将这两个存储库混合在一起并希望在其他一些时间点不需要任何方法(例如,我可能有一个检查userName是否被使用的方法 - 也许我会在其他地方需要它).
此外,如果我将它们合并在一起,我要么需要2个服务层才能进入同一个存储库,因为我认为网站的2个不同部分的所有逻辑都很长,我必须有像ValidateLogin(),ValdiateRegistrationForm()这样的名称,ValdiateLoginRetrievePassword()等
或者反正调用存储库,只是有一个奇怪的声音名称?
似乎很难创建一个具有足够通用名称的存储库,因此您可以将它用于应用程序的许多位置并且仍然有意义,我不认为在存储库中调用另一个存储库是一个好习惯吗?
使用带有通用存储库模式的EF5和ninject用于依赖性损害并在尝试使用存储过程与我的edmx将实体更新到数据库时遇到问题.
我在DbContextRepository.cs中的更新是:
public override void Update(T entity)
{
if (entity == null)
throw new ArgumentException("Cannot add a null entity.");
var entry = _context.Entry<T>(entity);
if (entry.State == EntityState.Detached)
{
_context.Set<T>().Attach(entity);
entry.State = EntityState.Modified;
}
}
Run Code Online (Sandbox Code Playgroud)
从我的AddressService.cs回到我的存储库我有:
public int Save(vw_address address)
{
if (address.address_pk == 0)
{
_repo.Insert(address);
}
else
{
_repo.Update(address);
}
_repo.SaveChanges();
return address.address_pk;
}
Run Code Online (Sandbox Code Playgroud)
当它命中Attach和EntityState.Modified时,它会发出错误:
ObjectStateManager中已存在具有相同键的对象.ObjectStateManager无法使用相同的键跟踪多个对象.
我已经查看了堆栈和互联网上的许多建议,但没有提出解决它的任何建议.任何工作都将受到赞赏.
谢谢!
c# entity-framework ninject repository-pattern entity-framework-5
我很难理解存储库模式.
关于该主题有很多意见,比如在Repository模式中做得正确,但其他东西如Repository是新的Singleton或者再次像在不使用DAO使用Repository或只是采取Spring JPA Data + Hibernate + MySQL + MAVEN在某种程度上存储库看起来与DAO对象相同.
我已经厌倦了阅读这些东西,因为imho这不是一件很难的事情,因为它在很多文章中都有展示.
我觉得这样:似乎我想要的是这样的:
------------------------------------------------------------------------
| Server |
------------------------------------------------------------------------
| | | |
Client <-|-> Service Layer <-|-> Repository Layer <-|-> ORM / Database Layer |
| | | |
------------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)
在Service Layer需要*DTO的对象,并将这些的Repository Layer,基本上不外乎谁知道"的人"更是如何一个实体可以存储.
例如,假设您有一些工具的组合(请注意,这只是伪代码)
@Entity
class ToolSet {
@Id
public Long id;
@OneToOne
public Tool tool1;
@OneToOne
public Tool tool2;
}
@Entity
class …Run Code Online (Sandbox Code Playgroud) 我在Entity Framework Code First上使用Generic Repository模式.一切都工作正常,直到我需要在查询中包含更多实体.我成功地包含了一个实体,但现在我无法弄清楚如何包含多个实体.看看到目前为止我得到了什么:
public IQueryable<TEntity> GetQuery<TEntity>() where TEntity : class
{
var entityName = GetEntityName<TEntity>();
return _objectContext.CreateQuery<TEntity>(entityName);
}
public IList<TEntity> GetQueryWithInclude<TEntity>(string toInclude) where TEntity : class
{
var entityName = GetEntityName<TEntity>();
return _objectContext.CreateQuery<TEntity>(entityName).Include(toInclude).ToList();
}
private string GetEntityName<TEntity>() where TEntity : class
{
return string.Format("{0}.{1}", _objectContext.DefaultContainerName, _pluralizer.Pluralize(typeof(TEntity).Name));
}
Run Code Online (Sandbox Code Playgroud)
我尝试但没有工作的是将一个字符串数组传递给一个函数,然后尝试在查询之上"追加"包含.我在想,如果我叫GetQueryWithInclude并在同一时间聚集查询的结果通过了实体名称(实际导航性能),但我担心这可能会重复在每次调用查询的结果...您认为最好的方法是什么?
提前致谢!
更新:
这是我想要实现的一个例子:
public IQueryable GetQueryWithIncludes(string[] otherEntities)
{
var entityName = GetEntityName<TEntity>();
//now loop over the otherEntities array
//and append Include extensions to the query
//so inside the loop, something …Run Code Online (Sandbox Code Playgroud) c# entity-framework repository-pattern entity-framework-4 ef-code-first
我最近学习了ASP.NET MVC(我喜欢它).我正在与一家使用依赖注入的公司合作,在每个请求中加载Repository实例,我熟悉使用该存储库.
但现在我正在编写自己的几个MVC应用程序.我不完全理解我公司使用的存储库的方法和原因,我正在尝试确定实现数据访问的最佳方法.
我正在使用C#和Entity Framework(包含所有最新版本).
我看到了处理数据访问的三种通用方法.
每次访问数据时,using语句中的常规DB上下文.这很简单,工作正常.但是,如果两个位置需要在一个请求中读取相同的数据,则必须读取两次数据.(每个请求使用一个存储库,两个地方都会使用相同的实例,我理解第二次读取只会返回第一次读取的数据.)
典型的存储库模式.由于我不理解的原因,这种典型的模式涉及为数据库中使用的每个表创建一个包装类.这对我来说似乎不对.事实上,由于它们也是作为接口实现的,我在技术上会为每个表创建两个包装类.EF为我创建表格.我不相信这种方法是有道理的.
还有一个通用存储库模式,其中创建单个存储库类以服务所有实体对象.这对我来说更有意义.但对别人有意义吗?链接是最好的方法吗?
我很想从其他人那里得到关于这个话题的一些意见.您是在编写自己的存储库,使用上述方法之一,还是完全不同的方式.请分享.
在.NET(Winforms,WPF,ASP.NET)上创建更大规模的企业级应用程序时,我看到两个主要的"思想流派".
有些人使用"存储库模式",它使用知道如何获取,插入,更新和删除对象的存储库.这些对象相当"愚蠢",因为它们不一定包含大量逻辑 - 例如,它们或多或少是数据传输对象.
另一个阵营使用我所谓的"智能"业务对象,它们知道如何加载自己,并且它们通常具有Save(),可能是Update()甚至Delete()方法.在这里,你真的不需要任何存储库 - 对象本身知道如何加载和保存自己.
最大的问题是:你使用或更喜欢哪种?为什么?
您是否在所有应用中使用相同的方法,或者您在选择一种方法时是否有任何特定标准?如果是的话 - 这些标准是什么?
我不是想在这里开始一场火焰战 - 只是试图找出每个人对此的看法以及你的观点是什么,以及为什么你使用一种(或两种)模式而不是另一种.
感谢任何建设性的意见!
结合Unit of Work并且Repository Pattern是现在相当广泛使用的东西.正如Martin Fowler 所说,使用的目的UoW是形成商业交易,同时不知道存储库实际如何工作(持续无知).我已经回顾了很多实现; 并忽略具体细节(具体/抽象类,接口,......),它们或多或少类似于以下内容:
public class RepositoryBase<T>
{
private UoW _uow;
public RepositoryBase(UoW uow) // injecting UoW instance via constructor
{
_uow = uow;
}
public void Add(T entity)
{
// Add logic here
}
// +other CRUD methods
}
public class UoW
{
// Holding one repository per domain entity
public RepositoryBase<Order> OrderRep { get; set; }
public RepositoryBase<Customer> CustomerRep { get; set; }
// +other repositories …Run Code Online (Sandbox Code Playgroud) 我正在学习存储库模式,正在阅读存储库模式,包括实体框架4.1和代码优先 和通用存储库模式 - 实体框架,ASP.NET MVC和单元测试三角 关于它们如何使用实体框架实现存储库模式.
话
•从上层隐藏EF
•使代码更易于测试
使代码更易于测试我理解,但为什么要从上层隐藏EF?
看看它们的实现,似乎只是用实体方法包装实体框架来查询实体框架.实际上是这样做的原因是什么?
我假设是为了
我理解正确吗?
如果我写一个DataAccessLayer,这是一个有方法的类
QueryFooObject(int id)
{
..//query foo from entity framework
}
AddFooObject(Foo obj)
{
.. //add foo to entity framework
}
......
QueryBarObject(int id)
{
..
}
AddBarObject(Bar obj)
{
...
}
Run Code Online (Sandbox Code Playgroud)
这也是一个存储库模式吗?
假人的解释会很棒:)
c# ×8
architecture ×2
asp.net-mvc ×2
java ×2
.net ×1
asp.net ×1
hibernate ×1
ninject ×1
repository ×1
spring ×1
unit-of-work ×1