goo*_*ate 16 repository appfabric appfabric-beta-2 azure-appfabric entity-framework-4.1
我希望尽可能灵活地使我的应用程序灵活,但不要让我的界面过于具体,从而陷入困境.
存储库的最佳对象类型是什么?IEnumerable,IQueryable还是List?
我正在考虑使用的技术是
Azure App Fabric缓存
实体框架4.1
可能是Windows Server AppFabric
这取决于您是否希望将来对该实体执行任何查询以及这些查询是否应该在内存中:
最近有一篇非常好的文章涵盖了这一点,即标题“返回 IQueryable 的存储库”。它是这么说的:
\n\n\n\n\n我们使用存储库模式的原因之一是封装胖查询。这些查询使得阅读、理解和测试 ASP.NET MVC 控制器中的操作变得困难。此外,随着应用程序的增长,在多个位置重复胖查询的机会也会增加。通过存储库模式,我们将这些查询封装在存储库类中。结果是更精简、更干净、更易于维护且更易于测试的操作。考虑这个例子:
\n\nRun Code Online (Sandbox Code Playgroud)\n\nvar orders = context.Orders\n .Include(o => o.Details)\n .ThenInclude(d => d.Product)\n .Where(o => o.CustomerId == 1234);\n这里我们直接使用 DbContext,而不使用存储库模式。当您的存储库方法返回 IQueryable 时,其他人将获取该 IQueryable 并在其上编写查询。这里\xe2\x80\x99是结果:
\n\nRun Code Online (Sandbox Code Playgroud)\n\nvar orders = repository.GetOrders()\n .Include(o => o.Details)\n .ThenInclude(d => d.Product)\n .Where(o => o.CustomerId == 1234);\n你能看出这两个代码片段之间的区别吗?唯一的区别在于第一行。在第一个示例中,我们使用context.Orders,在第二个示例中,我们使用repository.GetOrders()。那么,这个存储库解决了什么问题?没有什么!
\n\n您的存储库应该返回域对象。因此,GetOrders()方法应该返回IEnumerable。这样,第二个例子可以重写为:
\n\nvar 订单=repository.GetOrders(1234);
\n\n看到不同?
\n
因此,我在团队中添加了以下编码约定:
\n\n\n\n\n对于存储库类方法,永远不要返回IQueryable对象。始终首先枚举或转换它(例如,ToArray、ToList、AsEnumerable)。
\n
原因是IQueryable将允许调用者在此基础上进行构建并最终修改在数据库上执行的 SQL 查询。这对于数据库性能而言可能存在潜在危险,但更多的是与 SoC 相关。调用者不关心数据源;它只想要数据。
\n我想说使用IQueryable构建你的DAL,并传递它,确保你的对象争用生命周期是请求.这样您就可以获得延迟执行的好处,但是会面临数据库查询效率低下的风险.
然后确保性能测试您的应用程序(或至少最有可能获得流量的部分)并查看数据访问模式.在DAL中创建专门的方法来检索完全物化的onjects并将这些查询作为预编译的查询.
存储库接口的示例就像
public interface IDataContext
{
void Add<T>(T entity) where T : BaseEntity;
void Delete<T>(T entity) where T : BaseEntity;
IQueryable<T> Find<T>(Expression<Func<T, bool>> where) where T : BaseEntity;
}
Run Code Online (Sandbox Code Playgroud)
其中BaseEntity是我们所有类的基类,看起来,这个类没有映射到db中的任何表
public abstract class BaseEntity
{
public int Id { get; set; }
public DateTime CreateDateTime { get; set; }
public string CreateUser { get; set; }
public DateTime ModDateTime { get; set; }
public string ModUser { get; set; }
public byte[] RowVersion { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
Expression<Func<T, bool>> 将整个表达式传递给您的存储库而不仅仅是Func,因为EF在表达式上工作以生成sql查询,典型的用途是
ICollection<WFGroup> wgGroups = this.dataContext.Find<WFGroup>((w) => true).ToList();
Run Code Online (Sandbox Code Playgroud)
其中WFGroup是从BaseEntity派生的类,我通常使用延迟加载和代理,不要将对象分离/附加到上下文.