5

I have method which has LINQ query and query return columns from multiple tables.

How can I return that LINQ results object and catch it in caller method iterate results and assign to model class?

public ??? GetLocation(string CustomerNum)
    {
        if (!string.IsNullOrEmpty(CustomerNum))
        {
            var results = from ca in _context.CUS_ADDRESS
                           join cad in _context.CUS_ADDRESS_DETAIL on ca.CUS_ADDRESS_ID equals cad.CUS_ADDRESS_ID
                          where (cad.PRIORITY_SEQ == 0) && (ca.MASTER_CUSTOMER_ID == CustomerNum)
                           select new
                           {
                               CustomerNumber = ca.MASTER_CUSTOMER_ID,
                               ca.ADDRESS_1,
                               ca.ADDRESS_2,
                               ca.ADDRESS_3,
                               ca.ADDRESS_4,
                               ca.CITY,
                               ca.STATE,
                               ca.COUNTRY_DESCR,
                               cad.ADDRESS_TYPE_CODE,
                               cad.ADDRESS_STATUS_CODE
                           };
            return results;
        }
        else
        {
            return null;
        }
    }

Caller method

var results = Data.GetLocation(CustomerNum)
if (results.Any())
{
   var location = results.FirstOrDefault();
   .....
   .....
 }

What will be the GetLocation return type?

James123
  • 11,184
  • 66
  • 189
  • 343
  • 2
    Currently you'r trying to return a sequence with an element type which is an anonymous type. You probably want to create a `Location` type to use instead of your anonymous type. – Jon Skeet Oct 08 '13 at 18:13

5 Answers5

3

Depending on how you are actually using the results, you could return an IQueryable instead of IQueryable<T>.

I've used this in some situations (using IEnumerable), like WebForms, that have dynamic binding (either through Eval or by using a BoundField for instance.

julealgon
  • 7,072
  • 3
  • 32
  • 77
1

You are creating an anonymous object with select new, you can't return a collection of anonymous object from your function, instead you have to create a class which would have all the properties from your select statement and then return IQueryable<YourClass>

class YourClass
{
    public int CustomerNumber { get; set; }
    public string ADDRESS_1 { get; set; }
    //..............
}

and then :

var results = from ca in _context.CUS_ADDRESS
                           join cad in _context.CUS_ADDRESS_DETAIL on ca.CUS_ADDRESS_ID equals cad.CUS_ADDRESS_ID
                          where (cad.PRIORITY_SEQ == 0) && (ca.MASTER_CUSTOMER_ID == CustomerNum)
                           select new YourClass
                           {
                               CustomerNumber = ca.MASTER_CUSTOMER_ID,
                               ADDRESS_1 = ca.ADDRESS_1,
                               //...............

And modify your function return type as:

public IQueryable<YourClass> GetLocation(string CustomerNum)

You can look at this question for returning IQueryable or Not

Community
  • 1
  • 1
Habib
  • 219,104
  • 29
  • 407
  • 436
  • looks like it's `IQueryable`? – King King Oct 08 '13 at 18:16
  • 1
    But I need to have 'YouClass` two places library project (where LINQ defined) and another one in Caller project. I just want pass what ever LINQ return and Caller will take care for return values. – James123 Oct 08 '13 at 18:26
  • @KingKong I did same thing that you menthion in caller project. But now we are seperating LINQ to another library project so it can be reusable. – James123 Oct 08 '13 at 18:28
  • @James123 In that case you use a tool like [AutoMapper](http://automapper.org/) in the caller project to automatically translate from the library class to the caller class. – Scott Chamberlain Oct 08 '13 at 18:28
  • @James123, you can define `YourClass` in a single place and reference it from both the sender and caller, You can also return `List`, but don't. – Habib Oct 08 '13 at 18:29
1

If you didn't feel like creating a class you could use Tuples:

public IEnumerable<Tuple<int, string, string>> GetCustomer(int custId) { 
    return from p in customers
           where p.Id == custId
           select new Tuple<int, string, string>(
               p.Id,
               p.FirstName,
               p.LastName
           );
}

Though this means that you can't name their fields since you access the data like this:

var customer      = GetCustomer(1);
var custId        = customer.Item1;
var custFirstName = customer.Item2;
var custLastName  = customer.Item3;
Kittoes0124
  • 4,930
  • 3
  • 26
  • 47
0

Create a custom helper class having all columns as properties. Say its MyClass. Fill this as below. I know this not exactly what you want but will help you to get what you want.

var o= (from c in context.table1
        from d in context.table2
        where c.key=d.key
        select new MyClass
        {
           Property1=c.abc,
           Property2=d.xyz
        }).SingleOrDefault();

Or write your joins and where in such a way that it will give you only single row fron db.

Scott Chamberlain
  • 124,994
  • 33
  • 282
  • 431
0

In the function you are creating an anonymous object and hence cannot be used in caller without some methods of reflection. But it will be much easier to return an object like

public class CustomerLocation
{
public string CustomerNumber {get; set;}
// and so on
}

which will can be placed in a common layer and accessed by both caller and sender and use properties explicitly. For this your function is better be

public IQueryable<CustomerLocation> GetLocation(string CustomerNum)
{
// your code here
}
serene
  • 685
  • 6
  • 16