gpt4 book ai didi

repository - 如何将 Linq2NHibernate 的 .Fetch 和 .ThenFetch 包装到我的抽象存储库中?

转载 作者:行者123 更新时间:2023-12-02 22:59:05 24 4
gpt4 key购买 nike

我正在使用公开 IQueryable<T> 的通用存储库像这样:

public IQueryable<T> AllEntities
{
get
{
return session.Query<T>();
}
}

我可以这样查询:

var results =
(from e in repository.AllEntities
where e.SomeProperty == "some value"
select e).ToList();

但是,如果 T有一个父实体和祖 parent 实体,我想急切地加载它们,我必须这样做:

var results =
(from e in repository.AllEntities
where e.SomeProperty == "some value"
select e)
.Fetch(x => x.Parent)
.ThenFetch(x => x.Grandparent)
.ToList();

这可行,但是 .Fetch.ThenFetch都是 Linq2Nhibernate 特定的扩展方法,这导致了两个问题:

  1. 我必须包含 using NHibernate.Linq;我的文件顶部的声明。但是,在我执行此查询时,它应该与实现无关。

  2. 当我尝试对其进行单元测试时,.Fetch.ThenFetch针对 IQueryable<T> 执行时方法失败我的模拟存储库提供的。

我怎样才能将这些包裹在我的 IRepository<T> 中接口(interface),还是一些通用扩展方法内部?

更新:

到目前为止,我想到的就是将其添加到我的存储库界面:

IQueryable<T> EagerLoadParent<U>(IQueryable<T> query, 
Expression<Func<T, U>> parentExpression);
IQueryable<T> EagerLoadParent<U, V>(IQueryable<T> query,
Expression<Func<T, U>> parentExpression,
Expression<Func<U, V>> grandparentExpression);

...这是我的 NHibernate 存储库实现:

public IQueryable<T> EagerLoadParent<U>(IQueryable<T> query,
Expression<Func<T, U>> parentExpression)
{
return query
.Fetch(parentExpression);
}

public IQueryable<T> EagerLoadParent<U, V>(IQueryable<T> query,
Expression<Func<T, U>> parentExpression,
Expression<Func<U, V>> grandparentExpression)
{
return query
.Fetch(parentExpression)
.ThenFetch(grandparentExpression);
}

此 API 的使用者现在执行以下操作:

var query =
(from e in repository.AllEntities
where e.SomeProperty == "some value"
select e);
var results = repository
.EagerLoadParent(query, e => e.Parent, p => p.Grandparent)
.ToList();

但这缺乏我喜欢的良好扩展方法语法。我正在寻找更接近 .Fetch 的东西和.ThenFetch语法。

最佳答案

经过一番调查,我想我有一个秘诀:只要密切关注 NHibernate.Linq实现,以便拥有您自己的实现并避免客户端代码中显式的 NHibernate.Linq 依赖项。你只需要非常仔细地复制 NHibernate.Linq.EagerFetchingExtensionMethods类。

它需要一个接口(interface):IFetchRequest ,一个类FetchRequest实现IFetchRequest和一个静态类 EagerFetch实现扩展方法。这是 NHibernate.Linq.EagerFetchingExtensionMethods 的一种克隆。类。

只需定义:

public interface IFetchRequest<TQueried, TFetch> : IOrderedQueryable<TQueried> {}

模仿 NHibernate.Linq.INhFetchRequest<TQueried, TFetch>

然后定义一个实现:

public class FetchRequest<TQueried, TFetch> : IFetchRequest<TQueried, TFetch> {

#region IEnumerable<TQueried> Members

public IEnumerator<TQueried> GetEnumerator(){
return NhFetchRequest.GetEnumerator();
}

#endregion

#region IEnumerable Members

System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return NhFetchRequest.GetEnumerator();
}

#endregion

#region IQueryable Members

public Type ElementType {
get { return NhFetchRequest.ElementType; }
}

public System.Linq.Expressions.Expression Expression {
get { return NhFetchRequest.Expression; }
}

public IQueryProvider Provider {
get { return NhFetchRequest.Provider; }
}

#endregion

public FetchRequest(INhFetchRequest<TQueried, TFetch> nhFetchRequest){
NhFetchRequest = nhFetchRequest;
}

public INhFetchRequest<TQueried, TFetch> NhFetchRequest { get; private set; }
}

这个成员只保存一个 nHibernate 实现并将每个方法转发给该成员。

最后:

public static class EagerFetch {
/*
replacing methods from NHibernate.Linq.EagerFetchingExtensionMethods
private static INhFetchRequest<TOriginating, TRelated> CreateFluentFetchRequest<TOriginating, TRelated>(MethodInfo currentFetchMethod, IQueryable<TOriginating> query, LambdaExpression relatedObjectSelector);
public static INhFetchRequest<TOriginating, TRelated> Fetch<TOriginating, TRelated>(this IQueryable<TOriginating> query, Expression<Func<TOriginating, TRelated>> relatedObjectSelector);
public static INhFetchRequest<TOriginating, TRelated> FetchMany<TOriginating, TRelated>(this IQueryable<TOriginating> query, Expression<Func<TOriginating, IEnumerable<TRelated>>> relatedObjectSelector);
public static INhFetchRequest<TQueried, TRelated> ThenFetch<TQueried, TFetch, TRelated>(this INhFetchRequest<TQueried, TFetch> query, Expression<Func<TFetch, TRelated>> relatedObjectSelector);
public static INhFetchRequest<TQueried, TRelated> ThenFetchMany<TQueried, TFetch, TRelated>(this INhFetchRequest<TQueried, TFetch> query, Expression<Func<TFetch, IEnumerable<TRelated>>> relatedObjectSelector);
*/
public static IFetchRequest<TOriginating, TRelated> Fetch<TOriginating, TRelated>(this IQueryable<TOriginating> query, Expression<Func<TOriginating, TRelated>> relatedObjectSelector){
var fetch = EagerFetchingExtensionMethods.Fetch(query, relatedObjectSelector);
return new FetchRequest<TOriginating, TRelated>(fetch);
}

public static IFetchRequest<TOriginating, TRelated> FetchMany<TOriginating, TRelated>(this IQueryable<TOriginating> query, Expression<Func<TOriginating, IEnumerable<TRelated>>> relatedObjectSelector){
var fecth = EagerFetchingExtensionMethods.FetchMany(query, relatedObjectSelector);
return new FetchRequest<TOriginating, TRelated>(fecth);
}

public static IFetchRequest<TQueried, TRelated> ThenFetch<TQueried, TFetch, TRelated>(this IFetchRequest<TQueried, TFetch> query, Expression<Func<TFetch, TRelated>> relatedObjectSelector){
var impl = query as FetchRequest<TQueried, TFetch>;
var fetch = EagerFetchingExtensionMethods.ThenFetch(impl.NhFetchRequest, relatedObjectSelector);
return new FetchRequest<TQueried, TRelated>(fetch);
}

public static IFetchRequest<TQueried, TRelated> ThenFetchMany<TQueried, TFetch, TRelated>(this IFetchRequest<TQueried, TFetch> query, Expression<Func<TFetch, IEnumerable<TRelated>>> relatedObjectSelector){
var impl = query as FetchRequest<TQueried, TFetch>;
var fetch = EagerFetchingExtensionMethods.ThenFetchMany(impl.NhFetchRequest, relatedObjectSelector);
return new FetchRequest<TQueried, TRelated>(fetch);
}
}

关于repository - 如何将 Linq2NHibernate 的 .Fetch 和 .ThenFetch 包装到我的抽象存储库中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4809948/

24 4 0
文章推荐: angularjs - 如何使用 Angular 的 Protractor 0.24 版本在