【问题标题】:LINQ TO SQL am I missing something obvious here?LINQ TO SQL 我在这里遗漏了一些明显的东西吗?
【发布时间】:2009-10-28 19:59:31
【问题描述】:

我有这个方法,它将从 WCF 客户端调用,但对于我的测试,我使用的是本地“添加项目引用”。我收到一个错误,即在处理后无法调用 DataContext。

    public IEnumerable<Server> GetServers()
    {
        // initialze to null
        ServersDataContext sdc = null;

        try
        {
            // get connected
            using (sdc = GetDataContext())
            {
                // disable this deferred loading
                sdc.DeferredLoadingEnabled = false;

                var relations = from svr in sdc.Servers; // complex linq here

                // return
                return relations;
            }
        }
        catch (Exception ex)
        {
            LogError(ex, "fwizs.Internal");
            throw;
        }
        finally
        {
            if (sdc != null)
            {
                sdc.Dispose();
            }
        }
    }

这是我使用该方法的方式,它给出了以下错误:“无法访问已处置的对象。”

    if (da.GetServers()
        .Select(sv => sv.ServerID == s.ServerID).Count() == 0)
    {

        // do work since we found it
    }

对此返回的 IEnumerable 对象使用 .Select() 方法会尝试运行回数据库以进行选择。在为 WCF 序列化后,我认为这不会成为问题,但我希望我的本地测试能够正常工作。

【问题讨论】:

    标签: c# .net linq linq-to-sql


    【解决方案1】:

    在方法中具体化您的查询,以确保在处理数据上下文之前实际执行数据库调用。

    var relations = from svr in sdc.Servers;
    
    return relations.ToList();
    

    【讨论】:

      【解决方案2】:

      DeferredLoadingEnabled 属性控制如何加载关系,而不是如何加载主数据。

      您可以简单地使用 ToList 方法来确保将数据加载到内存中:

      return relations.ToList();
      

      【讨论】:

      • 他似乎对DeferredLoadingEnabled 没有做他认为应该做的事情感到特别困惑,所以我怀疑这个答案在这种特殊情况下最能提供信息。 +1。
      【解决方案3】:

      LINQ 是惰性的,所以这里只定义了查询,没有迭代槽。

      所以,发生的情况是您定义了查询,然后关闭了数据上下文。不久之后,您尝试迭代槽,这意味着您尝试通过之前已关闭的 SQL 连接进行查询。

      来自 MSDN:

      此方法是使用延迟执行实现的。立即返回值是一个存储执行操作所需的所有信息的对象。在通过直接调用其 GetEnumerator 方法或使用 Visual C# 中的 foreach 或 Visual Basic 中的 For Each 枚举对象之前,不会执行此方法表示的查询。

      【讨论】:

        【解决方案4】:

        以这种方式使用的“using”关键字是语法糖,一旦超出范围就可以保证处理 - 这发生在“返回关系”之后。

        【讨论】:

        • 即使出现异常?
        • @Nate:是的,这就是“使用”的全部意义所在。否则只写 x.Dispose() 会更容易。
        【解决方案5】:

        您已经使用 using 处理了您的数据上下文 所以你不能在 finally 中再次处理它

        【讨论】:

        • 即使无缘无故地处理了两次,但这不会导致错误。任何正确实现 IDisposable 的对象都可以被释放任意次数而不会造成伤害。
        【解决方案6】:

        除了其他人所说的使用 .ToList 之外,这也应该可以工作,并且具有延迟执行:

        public IEnumerable<Server> GetServers() {
            // initialze to null
            ServersDataContext sdc = null;
            try {
                // get connected
                using (sdc = GetDataContext()) {
                    // disable this deferred loading
                    sdc.DeferredLoadingEnabled = false;
                    foreach (var relation in from svr in sdc.Servers) // complex linq here
                        yield return relations;
                }
            }
            catch (Exception ex) {
                LogError(ex, "fwizs.Internal");
                throw;
            }
            finally {
                if (sdc != null) {
                    sdc.Dispose();
                }
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2011-05-14
          • 2019-03-12
          • 1970-01-01
          • 2013-07-12
          • 2014-06-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多