Entity Framework 和仓储模式问题

6
我正在使用通用存储库模式,并使用以下方法:

    private ObjectQuery<T> ObjectQueryList()
    {
        var list = CamelTrapEntities.CreateQuery<T>(EntitySetName);
        return list;
    }

    public IQueryable<T> List()
    {
        return ObjectQueryList();
    }

方法List()返回IQueryable<T>,因为IQueryable<T>易于模拟。我还有一个扩展方法:

    public static IQueryable<T> Include<T>(this IQueryable<T> obj, string path)
    {
        if (obj is ObjectQuery<T>)
            (obj as ObjectQuery<T>).Include(path);

        return obj;
    }

这个方法是在存储库之外使用的,用于获取已经加载了导航属性的实体列表,例如:List.Include("CreatedBy")。但问题在于它不起作用。所有包含操作都会被忽略掉。当我将List()方法更改为

    public ObjectQuery<T> List()
    {
        return ObjectQueryList();
    }

一切运行正常。

我该如何实现仓储模式以执行更复杂的查询?

3个回答

6
Reflector 给了我一个答案:


(注:此处为代码或标签,无法翻译)
public ObjectQuery<T> Include(string path)
{
    EntityUtil.CheckStringArgument(path, "path");
    return new ObjectQuery<T>(base.QueryState.Include<T>((ObjectQuery<T>) this, path));
}

Include方法返回一个新的ObjectQuery对象,而我的Include函数返回旧的对象。需要将代码更改为:

public static IQueryable<T> Include<T>(this IQueryable<T> obj, string path)
{
    if (obj is ObjectQuery<T>)
        return (obj as ObjectQuery<T>).Include(path);

    return obj;
}

问题已解决。虽然浪费了几个小时,但我更加讨厌实体框架 :)

这也让我意识到,我应该创建另一个带有包含参数的列表函数,并且不允许在存储库外部执行包含操作。


1

这里是我见过的最全面的EF Repository模式实现。我不能确定它是否允许您执行Include(),但如果我正确地阅读了实现,它应该可以。


1

使用EntityFramework 4.1,DbExtensions(System.Data.Entity.DbExtensions)解决了这个问题,并为任何IQueryable<T>本地添加了.Include([string path]).Include([property expression])

只需确保使用您的存储库的项目引用了EntityFramework,并且与任何扩展方法一样,在您的类文件中指定using System.Data.Entity;以访问这些扩展。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接