【问题标题】:Simulating Cross Context Joins--LINQ/C#模拟跨上下文连接--LINQ/C#
【发布时间】:2010-10-28 06:07:39
【问题描述】:

问题来了:

我有 2 个要加入的数据上下文。现在我知道 LINQ 不允许从一个上下文连接到另一个上下文,并且我知道 2 种可能的解决方案是创建单个数据上下文或具有 2 个单独的查询(这是我现在正在做的)。但是我想做的是“模拟”一个连接。

这是我尝试过的。

using (var _baseDataContext = Instance)
{
    var query = from a in _baseDataContext.Account.ACCOUNTs
                where a.STR_ACCOUNT_NUMBER.ToString() == accountID
                join app in _baseDataContext.Account.APPLICATIONs on a.GUID_ACCOUNT_ID equals
                            app.GUID_ACCOUNT
                join l in GetLoans() on app.GUID_APPLICATION equals l.GUID_APPLICATION
                select l.GUID_LOAN;

    return query.Count() > 0 ? query.First() : Guid.Empty;
}

private static IQueryable<LOAN> GetLoans()
{
    using (var _baseDataContext = Instance)
    {
        return (from l in _baseDataContext.Loan.LOANs
                select l).AsQueryable();
    }
}

在运行时我得到的是

System.InvalidOperationException:查询包含对在不同数据上下文中定义的项目的引用

编辑:

工作解决方案:

using (var _baseDataContext = Instance)
{
    var query = from a in _baseDataContext.Account.ACCOUNTs
                where a.STR_ACCOUNT_NUMBER.ToString() == accountID
                join app in _baseDataContext.Account.APPLICATIONs on a.GUID_ACCOUNT_ID equals
                           app.GUID_ACCOUNT
                join l in GetLoans() on app.GUID_APPLICATION equals l.GUID_APPLICATION 
                select l.GUID_LOAN;

     return (query.Count() > 0) ? query.First() : Guid.Empty;
}

private static IEnumerable<LOAN> GetLoans()
{
    using (var _baseDataContext = Instance)
    {
        return (from l in _baseDataContext.Loan.LOANs
                select l).AsQueryable();
    }
}

【问题讨论】:

    标签: c# entity-framework linq datacontext


    【解决方案1】:

    也许这样的事情可以让你朝着正确的方向开始。我根据您的列名制作了一个包含类似列的模拟数据库,并得到了一些结果。

        class Program
    {
        static AccountContextDataContext aContext = new AccountContextDataContext(@"Data Source=;Initial Catalog=;Integrated Security=True");
        static LoanContextDataContext lContext = new LoanContextDataContext(@"Data Source=;Initial Catalog=;Integrated Security=True");
    
        static void Main()
        {
    
            var query = from a in aContext.ACCOUNTs
                        join app in aContext.APPLICATIONs on a.GUID_ACCOUNT_ID equals app.GUID_ACCOUNT
                        where app.GUID_APPLICATION.ToString() == "24551D72-D4C2-428B-84BA-5837A25D8CF6"
                        select GetLoans(app.GUID_APPLICATION);
    
            IEnumerable<LOAN> loan = query.First();
            foreach (LOAN enumerable in loan)
            {
                Console.WriteLine(enumerable.GUID_LOAN);
            }
    
            Console.ReadLine();
        }
    
        private static IEnumerable<LOAN> GetLoans(Guid applicationGuid)
        {
            return (from l in lContext.LOANs where l.GUID_APPLICATION == applicationGuid select l).AsQueryable();
        }
    }
    

    希望这会有所帮助!

    【讨论】:

    • 我之前尝试过返回 IEnumerable,但收到了预期的转换错误。但是我没想过返回一个 IEnuerable AsQueryable.
    • 这种方法的一个潜在问题是您没有进行纯连接,因此如果您需要从贷款上下文中添加另一个连接,您将无法从我所看到的情况中进行操作。
    • 好的解决了。我们可以删除 Method 连接上的 where 子句,而不是从 Method 中进行选择,而只需进行纯连接。这里的技巧是该方法必须返回一个 IEnumerable.AsQueryable 这允许我们进行跨上下文连接,到目前为止我没有看到任何性能损失。
    【解决方案2】:

    这是我们发现的“解决方法”...

    我们从另一个数据库手动构建了我们的表,如果它在同一台服务器上,那么我们在表名前加上:

    <DatabaseName>.<SchemaName>.<YourTableName>
    

    如果它们位于链接服务器上,那么您还必须在其前面加上服务器名称:

    <ServerName>.<DatabaseName>.<SchemaName>.<YourTableName>
    

    这将允许您进行连接并且仍然返回一个未执行的 IQueryable... 这正是我们想要的。其他 2 种方式涉及加入内存中的 IEnumerables,这意味着您在进行联接(上图)之前为每个记录提取所有记录,并使用具有限制的 contains 方法进行 IQueryable 联接...

    希望将来 DataContext 将构建得足够聪明,知道如果服务器已链接,那么您可以在两个不同的服务器之间进行连接。

    【讨论】:

    • 虽然这是一个好主意,但在这种情况下,这不是一个选择。不过谢谢你的建议。
    【解决方案3】:

    我倾向于创建一个单独的数据上下文,其中只包含您要连接的两个表。但我想你可以在第二个上下文中维护一个临时表(包含第一个上下文中的数据),然后加入临时表。

    【讨论】:

    • 创建一个单独的数据上下文,只需要两个表是可能的,但这不是一个孤立的需求,它只是需要这个解决方案的一个例子。我想避免每次需要满足此需求时都创建隔离的数据上下文。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-22
    • 2022-11-10
    • 1970-01-01
    • 2017-04-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多