随着我深入研究DbContext,DbSet和相关接口,我想知道为什么你需要围绕这些实现实现一个单独的"通用"存储库?
它看起来像DbContext和IDbSet做你需要的一切,并在DbContext中包含"工作单元".
我在这里遗漏了什么,或者似乎人们喜欢无缘无故地添加另一层依赖.
我之前的问题让我再次思考层,存储库,依赖注入和这样的架构.
我的架构现在看起来像这样:
我首先使用EF代码,所以我只创建了POCO类和上下文.这创建了db和model.
级别更高的是业务层类(提供者).我为每个域使用不同的提供程序...比如MemberProvider,RoleProvider,TaskProvider等.我在每个提供程序中创建我的DbContext的新实例.
然后我在我的控制器中实例化这些提供程序,获取数据并将它们发送到Views.
我的初始架构包括存储库,我之所以摆脱它是因为我被告知它只会增加复杂性,所以为什么我不仅仅使用EF.我想这样做..直接从控制器使用EF,但我必须编写测试,它与真正的数据库有点复杂.我不得不假装 - 以某种方式模拟数据.因此,我为每个提供商创建了一个接口,并使列表中的硬编码数据成为假提供者.有了这个,我回到了一些东西,我不知道如何正确地进行.
这些事情开始过于复杂化......许多方法和"模式"......它产生了太多的噪音和无用的代码.
是否有任何SIMPLE和可测试的体系结构用于使用Entity Framework创建和ASP.NET MVC3应用程序?
architecture asp.net-mvc unit-testing entity-framework code-first
我仍然对存储库模式有些困惑.我想要使用此模式的主要原因是避免从域调用EF 4.1特定数据访问操作.我宁愿从IRepository接口调用泛型CRUD操作.这将使测试更容易,如果我将来必须更改数据访问框架,我将能够这样做,而无需重构大量代码.
这是我的情况的一个例子:
我在数据库中有3个表:Group,Person,和GroupPersonMap.GroupPersonMap是一个链接表,只包含主键Group和Person主键.我用VS 2010设计器创建了3个表的EF模型.EF很聪明,可以假设它GroupPersonMap是一个链接表,因此它不会在设计器中显示它.我想使用我现有的域对象而不是EF生成的类,所以我关闭了模型的代码生成.
我与EF模型匹配的现有类如下:
public class Group
{
public int GroupId { get; set; }
public string Name { get; set; }
public virtual ICollection<Person> People { get; set; }
}
public class Person
{
public int PersonId {get; set; }
public string FirstName { get; set; }
public virtual ICollection<Group> Groups { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我有一个通用的存储库接口,如下所示:
public interface IRepository<T> where T: class …Run Code Online (Sandbox Code Playgroud) c# domain-driven-design aggregateroot repository-pattern entity-framework-4.1
我想将值传递给DbContext的ctor,然后让该值对相关的DbSets强制执行"过滤".这可能......还是有更好的方法?
代码可能如下所示:
class Contact {
int ContactId { get; set; }
int CompanyId { get; set; }
string Name { get; set; }
}
class ContactContext : DbContext {
public ContactContext(int companyId) {...}
public DbSet<Contact> Contacts { get; set; }
}
using (var cc = new ContactContext(123)) {
// Would only return contacts where CompanyId = 123
var all = (from i in cc.Contacts select i);
// Would automatically set the CompanyId to 123
var contact = new Contact { …Run Code Online (Sandbox Code Playgroud) 我正在使用EF 4.1 Code First布局一个新的数据层,从较旧的自制数据层迁移.
我已经设置了两个程序集,一个用于我的上下文,一个用于所有POCO代码的第一个类.
我有一些业务逻辑,例如,对一个表(或几个表)的查询,这些表在几个不同的地方使用. 我应该把它放在哪里?
它不能进入POCO类,因为它连接了几个表,因此需要一个上下文.它可能会进入上下文,但是上下文会因数百个无组织的查询而变得臃肿. 所有业务逻辑都有共同的模式或安排吗?
在我的解决方案中,我有单元测试,它不依赖于数据库,而是具有外部依赖性(如数据库)的模拟和集成测试.
当我使用模拟进行单元测试时,使用LINQ to Object.当集成测试或实际程序运行时,使用LINQ to Entities,它比LINQ to Object更严格.
有没有办法在单元测试中复制LINQ To Object更严格的行为?
我最近了解了存储库和工作单元设计模式,并认为我将在新的EF4 MVC3项目中实现它们,因为抽象通常很好.
当我将它们添加到项目中时,我想知道果汁是否值得谚语挤压,给出以下内容:
我看到使用Repository模式的唯一真正好处是单元测试应用程序.抽象出数据存储似乎并不有用,因为我知道数据存储区不会改变,而且,EF4已经提供了一个非常好的抽象(我只是调用.AddObject(),它看起来像我在修改内存中集合,我只是调用.SaveChanges()已经提供了工作单元模式).
我是否应该费心实施这种抽象?我觉得必须有一些我遗漏的巨大好处,但我觉得我不需要沿着这条路走下去.我愿意相信; 有人可以提起诉讼吗?谢谢.
entity-framework unit-of-work repository-pattern asp.net-mvc-3
我有以下接口/类:
public interface IUnitOfWork : IDisposable
{
event EventHandler<EventArgs> Saved;
DbSet<T> Set<T>() where T : class;
DbEntityEntry<T> Entry<T>(T entity) where T : class;
void Commit();
}
Run Code Online (Sandbox Code Playgroud)
以及存储库的实现:
public class CachedSqlRepository<T, TKey, TContext> : ICacheRepository<T, TKey, TContext>
where T : class
where TContext : DbContext, IDisposable, new()
{
//A list of the Navigation Properties to include
private readonly Expression<Func<T, object>>[] _NavigationProperties;
public CachedSqlRepository(params Expression<Func<T, object>>[] navigationProperties)
{
_NavigationProperties = navigationProperties;
using (TContext dbContext = new TContext()) //Fetch the List of Entities …Run Code Online (Sandbox Code Playgroud) 我有一个很好的解耦应用程序和依赖注入的应用程序,它使用Entity Framework 4.1 CodeFirst通过存储库模式公开IQueryable.在测试存储库客户端时,很容易模拟底层数据存储区,但是没有捕获到某类错误:
存储库客户端可以自由地在存储库返回的内容上层叠自己的LINQ谓词,联接等:
{
_myRepository.FindAll().Where( x => x.Id == 3 && SomeMethod(x.Name) == "Hello" );
}
Run Code Online (Sandbox Code Playgroud)
这种查询将在模拟_myRepository的单元测试中成功,因为mock返回内存中的实体集合,而LINQ-to-Objects很乐意调用方法"SomeMethod".它将对真正的数据存储失败,因为"SomeMethod"不会转换为LINQ-to-Entities中的SQL.
我试图找出一种方法,我可以模拟数据集,并导致真正的EF查询提供程序生成(但不执行)SQL.为什么?因为测试应该很快,我不希望它们尽可能地打到真正的数据库.生成SQL将清除这样的翻译问题.
到目前为止,我还没有弄清楚如何做到这一点,因为在我的单元测试中,我最终无法控制查询何时实现.我想我需要提供我自己的IQueryable版本和各种LINQ Queryable扩展方法,或尝试通过提供程序机制挂钩(使用几年前做缓存/跟踪提供程序的示例.)这些似乎很多工作.关于如何实现这一点的任何想法?
.net unit-testing entity-framework mocking repository-pattern
c# ×3
unit-testing ×3
.net ×2
unit-of-work ×2
architecture ×1
asp.net-mvc ×1
code-first ×1
linq ×1
mocking ×1