【问题标题】:Trouble with Include extension on IObjectSet not workingIObjectSet 上的包含扩展无法正常工作的问题
【发布时间】:2010-11-09 09:53:19
【问题描述】:

谁能帮助我评估为什么下面的代码不起作用。在使用 IObjectset 时,我使用通用扩展方法来实现 Include。在我们的存储库中,我们看到它没有正确返回,所以我在测试应用程序中隔离了代码,如下所示。如果这可能被证明是相关的,我还包括了基于接口的 Context 以及相关模型部分的屏幕截图。这发生在 IObjectSet 属性上的所有 Includes 上,而不仅仅是我为本示例选择的 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")); }
    }
}

还有模特...

【问题讨论】:

  • 我使用了完全相同的设置,对我来说效果很好(对你没有帮助,但我想我提到了)。您是否已单步执行代码 - 是否调用了您的扩展方法,是否运行探查器跟踪等。
  • 分机。方法代码运行良好并调用数据库,但生成的查询只是忽略了 Includes 并且只返回了 Candidate。
  • @Daz Lewis - 你试过.Include("DPASelections").Include("DPASelections.DPAOption") 我不认为你可以直接进入双嵌套导航。 (我可能是错的)。保持简单,context.Candidates.Include("Grade").FirstOrDefault() 有效吗?
  • 顺便说一句 - 当您在 SO 上回复 cmets 时,请将该人的别名放在评论中 - 例如 @RPM1984,这样我会收到通知。我没有收到您的上述评论的通知。只是一个提示。
  • @RPM1984 - 使用扩展方法时,我的 Includes 都不起作用。在我的测试应用程序中,即使我在上下文中使用 ObjectSet 并尝试使用 foreach 从数组中创建包含,它们也不起作用。当我使用单个字符串直接针对 ObjectSet 上的 Include 时,“DPASelections.DPAOption”工作正常。失去了和这个人一起住在这里的意愿!顺便说一句 - 感谢@标记评论的提示。

标签: entity-framework


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    在 .Net 框架 4.0 中有一个内置的扩展方法 Include 只需添加 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
      });
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-30
      相关资源
      最近更新 更多