Linq和返回类型

时间:2011-01-08 05:51:16

标签: c# linq

我的GUI正在调用一个执行某些linq工作的服务项目,并将数据返回到我的GUI。但是,我正在与方法的返回类型作斗争。经过一番阅读后,我将此作为我的方法:

public static IEnumerable GetDetailedAccounts()
 {
 IEnumerable accounts =(from a in Db.accounts
                        join i in Db.financial_institution on  
                            a.financial_institution.financial_institution_id
                               equals i.financial_institution_id
                        join acct in Db.z_account_type on a.z_account_type.account_type_id 
                               equals acct.account_type_id
                        orderby i.name
                        select new 
                             {
                              account_id = a.account_id, 
                              name = i.name, 
                              description = acct.description
                              });
            return accounts;
}

然而,我的来电者正在争吵。我认为我搞砸了返回类型,或者没有很好地处理来电,但它并没有像我希望的那样工作。

这就是我尝试从GUI调用该方法的方法。

IEnumerable accounts = Data.AccountService.GetDetailedAccounts();

Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("Accounts:");
Console.ForegroundColor = ConsoleColor.White;

foreach (var acc in accounts)
  {
   Console.WriteLine(string.Format("{0:00} {1}", acc.account_id, acc.name + " " + acc.description));
  }

int accountid = WaitForKey();

然而,我的foreach和acc - 不起作用。 acc不知道我在方法中设置的名称,描述和ID。我至少接近正确吗?

3 个答案:

答案 0 :(得分:4)

@BrokenGlass是正确的,问题的根源是您使用的是匿名类型。这导致您使用IEnumerable的非泛型版本,该版本不知道对象的类型。

不是使用dynamic(这需要.NET 4.0,这可能会或可能不是您的问题),我建议您创建一个实际的Account类。

这样您就可以返回IEnumerable<Account>而非IEnumerable。然后,您将能够使用这些属性,因为它知道它是一个帐户。

创建帐户类后,您的方法将变为:

public static IEnumerable<Account> GetDetailedAccounts()
{
    IEnumerable<Account> accounts = (from a in Db.accounts
                    join i in Db.financial_institution on a.financial_institution.financial_institution_id
                        equals i.financial_institution_id
                    join acct in Db.z_account_type on a.z_account_type.account_type_id equals
                        acct.account_type_id
                    orderby i.name
                    select new Account {account_id = a.account_id, name = i.name, description = acct.description});
    return accounts;

}

然后调用代码可以保持不变。

我想我应该指出var不会像你想象的那样发挥作用。变量的类型仍然是编译时确定的,这意味着(大多数情况下)它只是一个快捷方式。您的示例与使用object而不是var的情况相同,因为IEnumerable只能包含object

如果您在.NET中工作,我建议遵循.NET命名约定,AccountId而不是account_id,但这不会影响它是否有效。

答案 1 :(得分:1)

问题是您使用的是该方法的用户无法回送的匿名类型。一个简单的出路(除了反射或创建一个类)将使用dynamic,因为你知道你想要访问的属性是:

示例:(我非常承认)

public static IEnumerable GetAccounts()
{
    return Enumerable.Range(0, 10)
           .Select(x => new { Id = x, Name = "herbert" });
}

//...
foreach (dynamic account in GetAccounts())
{
    Console.WriteLine(string.Format("Id: {0}, Name: {1}", 
                      account.Id, 
                      account.Name));
}

返回您的代码,这意味着只需更改调用代码:

foreach (dynamic acc in accounts)
{
    Console.WriteLine(string.Format("{0:00} {1}", acc.account_id, acc.name + " " + acc.description));
}

答案 2 :(得分:0)

Davy8是正确的,并且创建自定义BusinessObject(AccountDetail)对于长期外部库生命周期来说是更好的解决方案(如果您在逻辑/代码中使用此AccountDetail),因为您可以根据需要自定义它 具有转移类(AccountDetail)可以轻松地让您在设计时绑定到某个UI并使项目的概念更加清晰,您也可以更频繁地重复使用它

public class AccountDetail
{
public string AccountID{get;set;}
public string AccountName {get;set;}
public string AccountDescription {get;set}

public AccountDetail(){}
}

所以查询是:

public static List<AccountDetail> GetDetailedAccounts()
{
  return (from a in Db.accounts
         join i in Db.financial_institution on a.financial_institution.financial_institution_id
equals i.financial_institution_id
join acct in Db.z_account_type on a.z_account_type.account_type_id equals
acct.account_type_id
orderby i.name
select new AccountDetail 
{   AccountID = a.account_id, 
     AccountName= i.name, 
      AccountDescription= acct.description}

}).ToList();