views:

276

answers:

4

Ok, understand that I come from Cold Fusion so I tend to think of things in a CF sort of way, and C# and CF are as different as can be in general approach.

So the problem is: I want to pull a "table" (thats how I think of it) of data from a SQL database via LINQ and then I want to do some computations on it in memory. This "table" contains 6 or 7 values of a couple different types.

Right now, my solution is that I do the LINQ query using a Generic List of a custom Type. So my example is the RelevanceTable. I pull some data out that I want to do some evaluation of the data, which first start with .Contains. It appears that .Contains wants to act on the whole list or nothing. So I can use it if I have List<string>, but if I have List<ReferenceTableEntry> where ReferenceTableEntry is my custom type, I would need to override the IEquatable and tell the compiler what exactly "Equals" means.

While this doesn't seem unreasonable, it does seem like a long way to go for a simple problem so I have this sneaking suspicion that my approach is flawed from the get go.

If I want to use LINQ and .Contains, is overriding the Interface the only way? It seems like if there way just a way to say which field to operate on. Is there another collection type besides LIST that maybe has this ability. I have started using List a lot for this and while I have looked and looked, a see some other but not necessarily superior approaches.

I'm not looking for some fine point of performance or compactness or readability, just wondering if I am using a Phillips head screwdriver in a Hex screw. If my approach is a "decent" one, but not the best of course I'd like to know a better, but just knowing that its in the ballpark would give me little "Yeah! I'm not stupid!" and I would finish at least what I am doing completely before switch to another method.

Hope I explained that well enough. Thanks for you help.

+1  A: 

Ok, so if I'm reading this correctly you want to use the contains method. When using this with collections of objects (such as ReferenceTableEntry) you need to be careful because what you're saying is you're checking to see if the collection contains an object that IS the same as the object you're comparing against.

If you use the .Find() or .FindAll() method you can specify the criteria that you want to match on using an anonymous method.

So for example if you want to find all ReferenceTableEntry records in your list that have an Id greater than 1 you could do something like this

List<ReferenceTableEntry> listToSearch = //populate list here
var matches = listToSearch.FindAll(x => x.Id > 1);

matches will be a list of ReferenceTableEntry records that have an ID greater than 1.

having said all that, it's not completely clear that this is what you're trying to do.

lomaxx
I would add that collections use the .Equals method to test equality when using Contains. Also, Value types of course will not test for reference equality.
Ed Swangren
+2  A: 

What exactly is it you want to do with the table? It isn't clear. However, the standard LINQ (-to-Objects) methods will be available on any typed collection (including List<T>), allowing any range of Where, First, Any, All, etc.

So: what is you are trying to do? If you had the table, what value(s) do you want?

As a guess (based on the Contains stuff) - do you just want:

bool x= table.Any(x=>x.Foo == foo); // or someObj.Foo

?

Marc Gravell
+2  A: 

There are overloads for some of the methods in the List class that takes a delegate (optionally in the form of a lambda expression), that you can use to specify what field to look for.

For example, to look for the item where the Id property is 42:

ReferenceTableEntry found = theList.Find(r => r.Id == 42);

The found variable will have a reference to the first item that matches, or null if no item matched.

There are also some LINQ extensions that takes a delegate or an expression. This will do the same as the Find method:

ReferenceTableEntry found = theList.FirstOrDefault(r => r.Id == 42);
Guffa
A: 

Here is the LINQ query involved that creates the object I am talking about, and the problem line is:

.Where (searchWord => queryTerms.Contains(searchWord.Word))

List<queryTerm> queryTerms = MakeQueryTermList();

public static List<RelevanceTableEntry> CreateRelevanceTable(List<queryTerm> queryTerms)
   {
   SearchDataContext myContext = new SearchDataContext();
   var productRelevance = (from pwords in myContext.SearchWordOccuranceProducts
   where (myContext.SearchUniqueWords
   .Where (searchWord => queryTerms.Contains(searchWord.Word))
   .Select (searchWord => searchWord.Id)).Contains(pwords.WordId)
   orderby pwords.WordId
   select new {pwords.WordId, pwords.Weight, pwords.Position, pwords.ProductId});
   }

This query returns a list of WordId's that match the submitted search string (when it was List and it was just the word, that works fine, because as an answerer mentioned before, they were the same type of objects). My custom type here is queryTerms, a List that contains WordId, ProductId, Position, and Weight. From there I go about calculating the relevance by doing various operations on the created object. Sum "Weight" by product, use position matches to bump up Weights, etc. My point for keeping this separate was that the rules for doing those operations will change, but the basic factors involved will not. I would have even rather it be MORE separate (I'm still learning, I don't want to get fancy) but the rules for local and interpreted LINQ queries seems to trip me up when I do.

Since CF has supported queries of queries forever, that's how I tend to lean. Pull the data you need from the db, then do your operations (which includes queries with Aggregate functions) on the in-memory table.

I hope that makes it more clear.

zenWeasel
So I think by re-reading the answers and going back and doing more reading on Generic Collections I think I did validate my approach as at least viable and that I do need to override the default methods of List to do thing sepcific to my type. I also learned next time to ask a better question.
zenWeasel