Linq and return types

My GUI invokes a service project that does some linq work, and returns the data to my GUI. However, I struggle with the return type of the method. After some reading, I have this as my method:

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; } 

However, my subscriber is struggling a bit. I think I'm wrapping the return type or badly handling the caller, but it doesn't work as I hoped.

This is how I try to call a method from my 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(); 

However, my foreach and acc do not work. acc does not know about the name, description and identifier that I configure in the method. Am I at least close to the right one?

+4
source share
3 answers

@BrokenGlass is correct that the root of the problem is that you are using an anonymous type. This leads to the fact that you are using a non-generic version of IEnumerable, which does not know what type of objects are.

Instead of using dynamic though (which requires .NET 4.0, which may or may not be a problem for you), I would recommend creating an actual Account class.

That way you can return an IEnumerable<Account> instead of an IEnumerable . Then you can use the properties, as he knows that this is an account.

After creating the Account class, your method will look like this:

 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; } 

Then the calling code may remain the same.

I thought I should indicate that var does not work the way you probably think. The type of the variable is still determined by compilation time, which means (for the most part) it's just a shortcut. Your example will be identical if you used object instead of var , because IEnumerable can only contain object .

If you work in .NET, I would recommend following the .NET naming conventions, although AccountId instead of account_id , but this will not affect whether it works or not.

+4
source

The problem is that you are using an anonymous type, which the method user has no way to return. An easy way out (besides reflecting or creating a class) will use dynamic , since you know the necessary properties for access:

Example: (I really admitted)

 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)); } 

Return to your code, which would mean changing the calling code:

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

Davy8 is true, and creating a custom BusinessObject (AccountDetail) will be the best solution for the long-term life cycle of an external library (if you use this AccountDetail in your logic / code) since you can configure it the way you want.
having a transfer class (AccountDetail) easily allows you to bind to a certain user interface during development and make the concept of your project more understandable, you can also reuse it more often

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

therefore Query:

 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(); 
0
source

Source: https://habr.com/ru/post/1334734/


All Articles