0

Suppose I have the following class and objects:

class Product
{ 
   public int ProductId { get; set; }
   public string ProductDesc { get; set; }
} 

string[] keywordArray = new string []{"A", "B", "C", "D"};    

var products = repository.GetAllProducts();

I use var because GetallProducts() returns a IQueryable<Product> but I cannot "see" the Product type since it is defined in my DAL.

Now I need a temp variable tempResult to store temporary results in a foreach. For example:

foreach(var keyword in keywordArray)
{
    tempResult = tempresult.Union(products.Where(p => p.ProductDesc.Contains(keyword)));
}

If I declare var tempResult inside the foreach, it is overwritten at each iteration (and it will give a compile time error, because it cannot be used before its initialization).

Therefore I need to inizialize it outside the foreach. If I use:

var tempResult = products;

Inside my foreach I just sum up to the whole set my desidered resultSet.

Therefore the only two possible solutions are:

1) Create a method in the Repository that returns an empty IQueryable<Product> (factory pattern)

2) Use reflection (if feasible, not sure yet)

I found both solutions a bit "dirty". Is there any other approach/pattern to achieve this? Thanks

CiccioMiami
  • 8,028
  • 32
  • 90
  • 151
  • add a using statement for your Product namespace (you're accessing its members, you're gonna need it afaik). – Alex Mar 29 '12 at 12:00
  • @alex You can get away without a `using` statement if you're just e.g. reading properties inside a lambda; you only need it if you need to reference the class somewhere by name e.g. a constructor, declaring a variable etc. – Rawling Mar 29 '12 at 12:06

4 Answers4

2

Your code must be able to "see" the Product type since you're accessing ProductDesc and so on.

You just need to add a using statement for your DAL's namespace, or at worst set tempResult to Enumerable.Empty<My.DAL.Namespace.Product>();

Creating a whole method just to avoid referencing the namespace is unnecessary; using reflection is even worse.

On second thought, just call

var notTempResult = keywordArray.SelectMany(
    kw => products.Where(p => p.ProductDesc.Contains(kw)).Distinct();

to get your result without even having to reference the namespace.

Rawling
  • 49,248
  • 7
  • 89
  • 127
  • Thanks but I am a bit confused. According to the Unit of Work from my Service layer I cannot use variables defined in my DAL right? – CiccioMiami Mar 29 '12 at 15:58
  • I'm not sure what you mean here. There's no code-based reason this shouldn't work. – Rawling Mar 29 '12 at 19:44
  • No idea about your architecture. How do you propose to get anything out of your DAL if you can't use the classes defined in it? – Rawling Mar 30 '12 at 08:59
0
Dynamic tempResult = null;

foreach(var keyword in keywordArray)
{

    if (tempResult == null) {
        tempResult = products.Where(p => p.ProductDesc.Contains(keyword));
    }
    else {

        tempResult = tempresult.Union(products.Where(p => p.ProductDesc.Contains(keyword)));
    }
}
Quinton Bernhardt
  • 4,773
  • 19
  • 28
0

One option is to declare your tempResult as an IList and use a .ToList() on the union IEnumerable.

        string[] keywordArray = new string[] {"A", "B", "C", "D"};

        var products = repository.GetAllProducts();

        IList<Product> tempResult = new List<Product>();
        foreach (var keyword in keywordArray)
        {
            //declared because of access to modified closure issue.
            string keyword1 = keyword;
            tempResult = tempResult.Union(products.Where(p => 
               p.ProductDesc.Contains(keyword1))).ToList();
        }
alan
  • 76
  • 1
  • 4
  • 1
    If the questioner can't use `IQueryable` he won't be able to use `IList` or `List`. – Rawling Mar 29 '12 at 12:12
  • 1
    Ah, yes. I missed that part. I thought it seemed too easy :P – alan Mar 29 '12 at 12:14
  • Then I would try to redesign your repositories to not return IQueryable<>. It is considered by many to be bad practice. http://stackoverflow.com/questions/7322434/iqueryable-repositories-take-2 – alan Mar 29 '12 at 12:20
  • well the problem is that I have a lot of data, and I need to use IQueryable in order not to take too much memory. I populate the collection once all the filtering is done. The only drawback is that I cannot use LINQtoObjects methods in IQueryable – CiccioMiami Mar 29 '12 at 15:50
0

May be you can use linq expression and need not use any temporary variable.

 var result = products.Where(p => keywordArray.Contains(p.ProductDesc));
Prakash
  • 823
  • 12
  • 28