模拟跨上下文联接--LINQ/C#

25

问题如下:

我有两个数据上下文需要进行联接。现在我知道LINQ不允许从一个上下文到另一个上下文进行联接,我也知道两种可能的解决方案是创建单个数据上下文或者有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();
    }
}
4个回答

17

也许像这样可以帮助你朝着正确的方向开始。我用类似于你的列名的列制作了一个模拟数据库,并得到了一些结果。

    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<LOAN>,但是像预期的那样收到了一个转换错误。然而,我没有考虑过返回一个IEnuerable<LOAN> AsQueryable。 - David Yancey
这种方法的一个潜在问题是,你没有进行纯连接,因此如果你需要在贷款上下文之外添加另一个连接,从我所看到的情况来看,你将无法实现。 - David Yancey
1
好的,我解决了。 我们可以在 Method 连接上删除 where 子句,而不是从 Method 中选择,而是进行纯连接。这里的诀窍是方法必须返回 IEnumerable<T>.AsQueryable。这使我们能够进行跨上下文连接,到目前为止,我还没有看到任何性能损失。 - David Yancey

3
这是我们发现的“解决方法”...
我们手动从其他数据库中构建了我们的表格,并且如果它在同一服务器上,那么我们会在表名前加上前缀:
<DatabaseName>.<SchemaName>.<YourTableName>

如果它们在一个联接服务器上,则还必须使用服务器名称作为前缀:

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

这将允许您进行连接,同时返回一个未执行的IQueryable...这正是我们想要的。 另外两种方法涉及在内存中连接IEnumerables,这意味着您需要在执行连接之前拉取每个记录,并使用包含方法进行IQueryable连接,该方法具有一定的限制...希望将来的DataContext能够智能构建,知道如果服务器已链接,则可以在两个不同的服务器之间进行连接。

虽然那是个好主意,但在这种情况下不可行。谢谢你的建议。 - David Yancey

0
您可以在数据库B中创建一个视图,该视图代表数据库A中的表。然后在上下文B模型中,对该视图进行建模,以便您可以连接表格。
Create View vw_Stuff AS
Select prop1,
       prop2 
from otherDb..Stuff

0

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


创建一个仅需要这两个表的单独数据上下文是可能的,但这不是孤立的需求,它只是这种解决方案的一个例子。我想避免每次需要满足这种需求时都创建一个孤立的数据上下文。 - David Yancey

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