gpt4 book ai didi

asp.net-mvc-3 - 将其转化为通用存储库模式

转载 作者:行者123 更新时间:2023-12-02 05:08:49 26 4
gpt4 key购买 nike

我已经开始将项目转换为通用存储库和工作单元模式。到目前为止,我已经能够将 Controller 中的所有直接上下文引用反向工程到通用存储库;但是,我遇到了以下两行代码的问题:

`context.Entry(ticket).Collection(i => i.TicketItems).Load();
ticket.TicketItems.Clear();`

这是我的 Controller 在删除 TicketTicketItem 之间的任何引用之前所做的。 TicketTicketItem 之间存在多对多关系。所以这两行代码就是我之前用来从 Ticket

中删除所有 TicketItems 的代码

最佳答案

您可以在存储库界面中使用两种方法 - 一种用于导航引用,一种用于导航集合:

public interface IRepository<T>
{
void LoadNavigationReference<TReference>(T entity,
Expression<Func<T, TReference>> navigationProperty,
params Expression<Func<TReference, object>>[] includes)
where TReference : class;

void LoadNavigationCollection<TElement>(T entity,
Expression<Func<T, ICollection<TElement>>> navigationProperty,
params Expression<Func<TElement, object>>[] includes)
where TElement : class;
}

它们应该也支持包含其他嵌套导航属性。实现将是:

public class Repository<T> : IRepository<T>
where T : class
{
private readonly MyContext _dbContext;

public Repository(MyContext dbContext)
{
_dbContext = dbContext;
}

public void LoadNavigationReference<TReference>(T entity,
Expression<Func<T, TReference>> navigationProperty,
params Expression<Func<TReference, object>>[] includes)
where TReference : class
{
if (includes == null || includes.Length == 0)
_dbContext.Entry(entity).Reference(navigationProperty).Load();
else
_dbContext.Entry(entity).Reference(navigationProperty).Query()
.IncludeMultiple(includes).Load();
}

public void LoadNavigationCollection<TElement>(T entity,
Expression<Func<T, ICollection<TElement>>> navigationProperty,
params Expression<Func<TElement, object>>[] includes)
where TElement : class
{
if (includes == null || includes.Length == 0)
_dbContext.Entry(entity).Collection(navigationProperty).Load();
else
_dbContext.Entry(entity).Collection(navigationProperty).Query()
.IncludeMultiple(includes).Load();
}
}

IncludeMultiple上面使用的扩展方法取自Ladislav Mrnka's answer here .

您问题中的示例将如下所示:

repository.LoadNavigationCollection(ticket, i => i.TicketItems);
ticket.TicketItems.Clear();

哪里repository类型为 IRepository<Ticket> .

如果TicketItem有另一个导航属性,比如 TicketItemDetails , 你可以急切地将它与 TicketItems 一起加载这样:

repository.LoadNavigationCollection(ticket, i => i.TicketItems,
t => t.TicketItemDetails);

编辑

顺便说一句,关于通用存储库的重要旁注:上面是一个通用存储库的一部分,它实际上有 16 种方法,我在项目的早期阶段使用过,然后才停止扩展它并完全放弃这种风格。

存储库一开始有大约 5 个方法(就像您在 Internet 上看到的大多数常见存储库一样)。只使用这 5 种方法而不损失很多 Entity Framework 的功能是不可能的。因此,我需要根据项目中的实际需求逐步扩展它,并且在我将其从项目中删除之前它一直没有“完成”。

问题是:如果您向某人展示该界面(“这里我有一个 super 通用且技术独立的数据访问界面”),他会立即说“啊哈,您正在使用 Entity Framework!”。原因是几乎每个方法都只是 Entity Framework 方法的包装器,您不能通过为接口(interface)方法使用其他名称来隐藏它。整个界面都有 EF 的味道 DbContext/代码优先。

现在,尝试使用 Entity Framework 之外的另一种技术来实现该接口(interface)。您很可能会遇到与我遇到的相同问题:缺少很多方法来利用其他技术的强大功能,或者现有方法的参数错误,或者您无法合理地使用其他方法实现太多方法技术。

我什至失败并失去了为单元测试构建该接口(interface)的内存中实现的所有乐趣。

在我看来,这样的通用存储库是 Leaky Abstraction 的典型示例您想到的真正实现会在整个界面中闪耀。

但是,如果您不能抽象出 Entity Framework 的用法,那么构建一个通用的存储库接口(interface)就毫无意义了。

关于asp.net-mvc-3 - 将其转化为通用存储库模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15844721/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com