IObjectSet上的Include扩展无法正常工作

时间:2010-11-09 09:53:20

标签: entity-framework

任何人都可以帮我评估下面代码无效的原因。我在使用IObjectset时使用公共扩展方法来实现Include。在我们的存储库中,我们看到这没有正确返回所以我已经在测试应用程序中隔离了代码,如下所示。如果这可能证明是相关的,我还包括基于接口的Context,以及相关模型部分的屏幕截图。 IObjectSet属性上的所有包含都会发生这种情况,而不仅仅是我为此示例选择的DPASelections。

如果我更新上下文以返回ObjectSet(仍然使用POCO实体)而不是IObjectSet,那么一切正常。当使用IObjectSet和扩展方法并逐步执行代码时,我看到扩展方法正在通过调用我们正在转换的ObjectQuery正确完成,但是包含的实体永远不会返回到图形上。如上所述,当我不接口Context并返回ObjectSet属性因此直接在ObjectSet上调用Include时,这非常有效。

我在执行查询时没有出现任何错误,因此这与SO上涉及编译查询的其他几个问题不同。

有没有其他人遇到过这种扩展方法实施的问题,或者有人能发现我在这里做错了吗?

非常感谢任何帮助。

        static void Main(string[] args)
    {
        using (var context = new AssocEntities())
        {
            context.ContextOptions.LazyLoadingEnabled = false;
            Candidate candidate = context.Candidates
                                        .Include("DPASelections.DPAOption")
                                        .SingleOrDefault(c => c.Number == "N100064");

            //Count is 0 when using ext. method and IObjectSet through AssocContext but correct when using Include
            //on ObjectSet through AssocContext
            Console.WriteLine("DPASelection count = {0}",candidate.DPASelections.Count);

            //This is always null when using IObjectSet and ext. method but populated
            //when using Include on ObjectSet
            var option = candidate.DPASelections.First().DPAOption;

            Console.WriteLine("First DPAOption = {0} : {1}",option.Id,option.Text);

        }

        Console.ReadLine();
    }
}

public static class Extensions
{
    public static IQueryable<TSource> Include<TSource>(this IQueryable<TSource> source, string path)
    {
        var objectQuery = source as ObjectQuery<TSource>;

        if (objectQuery != null)
        {
            objectQuery.Include(path);
        }

        return source;
    }
}

//Subset of custom context implementing IObjectSet as returns.
//Works fine when I return ObjectSet rather than IObjectSet and use
//the Include method directly
public partial class AssocEntities : ObjectContext
{
    public const string ConnectionString = "name=AssocEntities";
    public const string ContainerName = "AssocEntities";

    #region Constructors

    public AssocEntities()
        : base(ConnectionString, ContainerName)
    {
        this.ContextOptions.LazyLoadingEnabled = true;
    }

    public AssocEntities(string connectionString)
        : base(connectionString, ContainerName)
    {
        this.ContextOptions.LazyLoadingEnabled = true;
    }

    public AssocEntities(EntityConnection connection)
        : base(connection, ContainerName)
    {
        this.ContextOptions.LazyLoadingEnabled = true;
    }

    #endregion

    #region IObjectSet Properties

    public IObjectSet<Address> Addresses
    {
        get { return _addresses ?? (_addresses = CreateObjectSet<Address>("Addresses")); }
    }
    private IObjectSet<Address> _addresses;

    public IObjectSet<Answer> Answers
    {
        get { return _answers ?? (_answers = CreateObjectSet<Answer>("Answers")); }
    }
    private IObjectSet<Answer> _answers;

    public IObjectSet<Candidate> Candidates
    {
        get { return _candidates ?? (_candidates = CreateObjectSet<Candidate>("Candidates")); }
    }
}

模特...... alt text

2 个答案:

答案 0 :(得分:1)

我需要将objectQuery.Include(path);替换为objectQuery = objectQuery.Include(path);

答案 1 :(得分:0)

在.Net framework 4.0中,Include有一个内置的Extentionmethod 只需添加System.Data.Entity命名空间。

它使用反射 - 这是它的工作原理:

private static T CommonInclude<T>(T source, string path)
{
  MethodInfo method = source.GetType().GetMethod("Include", DbExtensions.StringIncludeTypes);
  if (!(method != (MethodInfo) null) || !typeof (T).IsAssignableFrom(method.ReturnType))
    return source;
  return (T) method.Invoke((object) source, new object[1]
  {
    (object) path
  });
}