我在重用 EF 5 的包含时遇到问题。我做错了什么?



我对下面的代码有一个问题。

public IEnumerable<BillingConfiguration> GetBillingConfigurationsForAccount(int accountId, DateTime? effectiveDate)
    {
        var result = new List<BillingConfiguration>();
        var accountIds = new List<int>();
        var billingGroupIds = new List<int>();
        using (var context = new GbContext())
        {
            var account = context.Accounts.Where(a => a.AccountId == accountId).SingleOrDefault();
            if (account.ParentAccountId == null) // This is a parent account
            {
                // Get list of sub account ids
                accountIds = context.Accounts.Where(a => a.ParentAccountId == accountId).Select(x => x.AccountId).ToList();
                accountIds.Add(accountId);
            }
            else // This is a sub account
            {
                accountIds.Add(accountId);
            }
            // Get list of Billing Configurations for all accountIds
            IQueryable<BillingConfigurationAccount> accountQuery = context.BillingConfigurationAccounts
                .Where(a => accountIds.Contains(a.AccountId)).AsQueryable();
            AddBillingConfigurationAccountIncludes(accountQuery);
            var accountBillingConfigurations = accountQuery.ToList();
            //IQueryable<BillingConfigurationAccount> accountQuery = context.BillingConfigurationAccounts;
            //AddBillingConfigurationAccountIncludes(accountQuery);
            //accountQuery = accountQuery.Where(a => accountIds.Contains(a.AccountId));
            //var accountBillingConfigurations = accountQuery.ToList();   
            if (accountBillingConfigurations.HasValues())
            {
                accountBillingConfigurations.ForEach(x => result.Add(x.BillingConfiguration));
            }
            return result;
        }
    }
private void AddBillingConfigurationAccountIncludes(IQueryable<BillingConfigurationAccount> query)
    {
        query = query
            .Include(p => p.BillingConfiguration)
            .Include(p => p.BillingConfiguration.BillingConfigurationLevel)
            .Include(p => p.BillingConfiguration.BillType)
            .Include(p => p.BillingConfiguration.PayerOptionType)
            .Include(p => p.BillingConfiguration.BillModeOptions)
            .Include(p => p.BillingConfiguration.BillModeOptions.Select(m => m.BillMode))
            .Include(p => p.BillingConfiguration.BillModeOptions.Select(m => m.FirstPastDueDateOptionsType))
            .Include(p => p.BillingConfiguration.BillModeOptions.Select(m => m.LapseNoticeOptionsType))
            .Include(p => p.BillingConfiguration.BillModeOptions.Select(m => m.PaymentDueDateOptionsType))
            .Include(p => p.BillingConfiguration.BillModeOptions.Select(m => m.PaymentGracePeriodType))
            .Include(p => p.BillingConfiguration.BillModeOptions.Select(m => m.SecondPastDueDateOptionsType))
            .Include(p => p.BillingConfiguration.BillModeOptions.Select(m => m.BillModeOptionPaymentMethods))
            .Include(p => p.BillingConfiguration.BillModeOptions.Select(m => m.BillModeOptionPaymentMethods.Select(n => n.PaymentMethodType)));
    }

当我查看accountBillingConfigurations时,它在列表中有2个项目,然而BillingConfiguration实体为空,BillingConfigurationId存在并且正确,但它没有带回BillingConfiguration实体。

现在,如果我像这样做所有内联,它会像预期的那样工作。where子句和include是相同的。

public IEnumerable<BillingConfiguration> GetBillingConfigurationsForAccount(int accountId, DateTime? effectiveDate)
    {
        var result = new List<BillingConfiguration>();
        var accountIds = new List<int>();
        var billingGroupIds = new List<int>();
        using (var context = new GbContext())
        {
            var account = context.Accounts.Where(a => a.AccountId == accountId).SingleOrDefault();
            if (account.ParentAccountId == null) // This is a parent account
            {
                // Get list of sub account ids
                accountIds = context.Accounts.Where(a => a.ParentAccountId == accountId).Select(x => x.AccountId).ToList();
                accountIds.Add(accountId);
            }
            else // This is a sub account
            {
                accountIds.Add(accountId);
            }
            // Get list of Billing Configurations for all accountIds
            var accountBillingConfigurations = context.BillingConfigurationAccounts
                .Include(p => p.BillingConfiguration)
                .Include(p => p.BillingConfiguration.BillingConfigurationLevel)
                .Include(p => p.BillingConfiguration.BillType)
                .Include(p => p.BillingConfiguration.PayerOptionType)
                .Include(p => p.BillingConfiguration.BillModeOptions)
                .Include(p => p.BillingConfiguration.BillModeOptions.Select(m => m.BillMode))
                .Include(p => p.BillingConfiguration.BillModeOptions.Select(m => m.FirstPastDueDateOptionsType))
                .Include(p => p.BillingConfiguration.BillModeOptions.Select(m => m.LapseNoticeOptionsType))
                .Include(p => p.BillingConfiguration.BillModeOptions.Select(m => m.PaymentDueDateOptionsType))
                .Include(p => p.BillingConfiguration.BillModeOptions.Select(m => m.PaymentGracePeriodType))
                .Include(p => p.BillingConfiguration.BillModeOptions.Select(m => m.SecondPastDueDateOptionsType))
                .Include(p => p.BillingConfiguration.BillModeOptions.Select(m => m.BillModeOptionPaymentMethods))
                .Include(p => p.BillingConfiguration.BillModeOptions.Select(m => m.BillModeOptionPaymentMethods.Select(n => n.PaymentMethodType)))
                .Where(a => accountIds.Contains(a.AccountId));
            if (accountBillingConfigurations.HasValues())
            {
                accountBillingConfigurations.ForEach(x => result.Add(x.BillingConfiguration));
            }
            return result;
        }
    }

该代码实际上填写了BillingConfiguration实体及其所有子实体。我想做的事有可能吗?如果我做错了什么?

谢谢

这是一个微妙的问题。

您可以正确地假设像

这样的方法
void SomeMethod(IQueryable<T> query)

可以修改它接收到的引用对象,并且这些修改将在方法作用域之外可见。

然而

…该方法不修改对象,而是替换对象。赋值=Include方法的返回值赋给query变量。现在方法中,前面的query变量超出了作用域,因为引用被对新对象的引用覆盖了。但是方法之外,这个新的引用将永远不会被知道。这里,旧的引用仍然适用。

补救方法很简单:返回新的引用:
IQueryable<T> SomeMethod(IQueryable<T> query)

在你的情况下,这将变成:

accountQuery = AddBillingConfigurationAccountIncludes(accountQuery);

如果你不相信我,试试这个小程序在Linqpad:)

void Main()
{
    var ints = Enumerable.Range(1,10).ToArray();
    AddInt(ints, 11);
    ints.Dump();
}
void AddInt(IEnumerable<int> list, int i)
{
    list = list.Concat(new[] {i});
    list.Dump();
}

相关内容

  • 没有找到相关文章

最新更新