I have the code below but it give me an error at
.Where(p => Regex.Replace(p.Phone, rgPattern, "") == Regex.Replace(phone.Trim(), rgPattern, "")
string rgPattern = #"[\\\/:\*\?""<>|()-]";
var members = from m in Context.Members select m;
if (!String.IsNullOrEmpty(phone))
members = members.Where(p => Regex.Replace(p.Phone, rgPattern, "") == Regex.Replace(phone.Trim(), rgPattern, ""));
I know the LINQ commnand is not executed until I run:
members.OrderBy(orderBy).Skip(startRow).Take(maxRows).ToList();
Any idea in how to clean the value before comparing?
This is probably a problem with your data architecture. This is why we keep the data clean in the tables all of the time -- so you don't have to do evil things like this.
You have a couple of options here:
Clean up your actual data and add protections on the data layer to keep your phone numbers pure.
Create a view or computed column in your data which cleans up the phone number on the data layer, then map to that clean phone number and query off of that column instead.
Call ToList() on a subset of your rows before running your regex-based query and then use Linq to Objects to run the regex against those rows. This may be prohibitive if you can't narrow down your rows enough before using Linq to Objects.
Related
So I'm using PLINQO Linq2Sql on a large project. I was wondering if there was any way I could count the number of queries that get submitted to the SqlServer via code using either PLINQO or Linq2Sql?
Like if I wrote the code
var a = Tables.Users.FirstOrDefault(x=>x.Username == username);
var b = Tables.Apples.Where(x=>x.UID == a.UID).ToList();
var c = Tables.Pears.Where(x=>x.UID == a.UID);
The result would be 2 since the third one is still just an IQueryable.
Well, not something you want to do in a production environment.
I do not have a solution, but I guess you could start with the log property
http://msdn.microsoft.com/en-us/library/system.data.linq.datacontext.log.aspx
and code something around it.
I've got records in my MySQL projects database that have several boolean flags to help me sort the data. I have 3 categories planning, landscape, and environmental and 4 classes (or subcategories) for each category; industrial, government, education, residential.
My goal is to use ColdFusion to create and store the project_id numbers in an array of some kind that will basically have the projects sorted by category and class. That way I can grab just the industrial projects in the planning category and construct a link to that project.
So, the first position in the array would be planning and inside that first position would be the 4 classes, then, within that would be all of the project_id numbers that returned true for those particular criteria.
The logic I'm looking to create goes like this...
Loop over the query result, if planning = true and industrial = true, place the project id # into the planning array inside the industrial array.
How can I use <cfloop> to loop over the list of project records, recognize the category and class flags and construct a clean and usable dataset? Can this be handles in the query in some way?
Figure out the desired data structure
look at your existing data structure
figure out the algorithm to translate from one to the other
You may cfloop the query, and use a large cfswitch (or large set of if-then-else) to figure out how you want to store the id in your desired data structure. Or if you can map the class/category name as a struct key, then it might be easier.
Or you may use cfoutput group="" if it helps (cfloop group="" is available on in CF10+)
Finally, maybe you don't even need the data structure, just use Query of Queries wherever you need.
You may be able to utilize the Underscore.cfc library for this. For example, you could use the filter function to extract an array of structs representing the query rows you want:
planningArray = _.filter(queryResult, function(row){
return (row.planning == true && row.industrial == true);
});
I have the following query
#initial_matches = Listing.find_by_sql(["SELECT * FROM listings WHERE industry = ?", current_user.industry])
Is there a way I can run another SQL query on the selection from the above query using a each do? I want to run geokit calculations to eliminate certain listings that are outside of a specified distance...
Your question is slightly confusing. Do you want to use each..do (ruby) to do the filtering. Or do you want to use a sql query. Here is how you can let the ruby process do the filtering
refined list = #initial_matches.map { |listing|
listing.out_of_bounds? ? nil : listing
}.comact
If you wanted to use sql you could simply add additional sql (maybe a sub-select) it into your Listing.find_by_sql call.
If you want to do as you say in your comment.
WHERE location1.distance_from(location2, :units=>:miles)
You are mixing ruby (location1.distance_from(location2, :units=>:miles)) and sql (WHERE X > 50). This is difficult, but not impossible.
However, if you have to do the distance calculation in ruby already, why not do the filtering there as well. So in the spirit of my first example.
listing2 = some_location_to_filter_by
#refined_list = #initial_matches.map { |listing|
listing.distance_from(listing2) > 50 ? nil : listing
}.compact
This will iterate over all listings, keeping only those that are further than 50 from some predetermined listing.
EDIT: If this logic is done in the controller you need to assign to #refined_list instead of refined_list since only controller instance variables (as opposed to local ones) are accessible to the view.
In short, no. This is because after the initial query, you are not left with a relational table or view, you are left with an array of activerecord objects. So any processing to be done after the initial query has to be in the format of ruby and activerecord, not sql.
I have an IQueryable object which is the result of view (using a data model in Visual Studio).
I want to apply an additional filter on the object, but I don't want it to go back to the database and run the query again with the additional where clause. The query takes several seconds to run so I'd like linq to simply filter the current list rather than regenerating the query.
How do I prevent linq to sql going back to the database when I execute a .where() function?
To answer the title of the question, you can generally use AsEnumerable to make subsequent bits execute locally:
var query = db.People
.Where(p => p.Age > 18) // In database
.AsEnumerable()
.Where(p => p.Name == "Jon") // In .NET
The call to AsEnumerable doesn't do anything other than change the static type from IQueryable<T> to IEnumerable<T> so that the extension methods in Enumerable get called instead of those in Queryable.
However, if you reuse a query that's already executed, it will still execute again in the database... so (to answer the body of the question) if you want to reuse a query's results, you need to convert them into a list first, e.g.
var results = db.People
.Where(p => p.Age > 18)
.ToList();
Then accessing results won't go back to the database (unless it needs to fetch child values, of course). So you can do:
var subquery = results.Where(p => p.Name == "Jon");
That will perform the filtering in process instead.
use ToList() after first execution and use the generated list in the rest of your code.
var products = (from p in Products where p.Name.Contains("k") select p).ToList(); // this will go to database and fill the products list.
var x = products.Where(p => p.ProductionDate > DateTime.Now); // this will run in memory.
I am working on a database access layer project and decided to use Linq to SQL for it. One of the things I wanted to do was provide an API that can take Linq Expressions as arguments to retrieve data. For instance, I wrote this API now that looks like this:
public Result GetResults(System.Linq.Expressions.Expression<Func<Result, bool>> predicate)
{
Result result = db.Results.SingleOrDefault(predicate);
return result;
}
You can then use this API to query the database for a Result row that satisfies certain conditions, for example:
Result result = Provider.GetResults(r => r.ID == 11);
This works very well. I am able to get the one row I want based on my conditions.
Next step was taking this to be able to get multiple objects back from the database.
The way I got it to work was like this:
public List<Result> GetResults(System.Linq.Expressions.Expression<Func<Result, bool>> predicate)
{
List<Result> results = db.Results.Select(r => r).Where(r => r.ID == 11).ToList<Result>();
return results;
}
As you can see, I call a Select with r => r, this gives me back everything and then I use a Where to filter to what I need.
It works... but something tells me that I am doing it really ugly. I could be wrong, but doesn't this pull EVERYTHING out of the Results table then filters it? or does it put together the correct SQL statement that does filter at the database level?
Anyway... I would highly appreciate some guidance on how I can accomplish this task. How do I write an API that takes a Linq Expression as an argument and returns a set of objects from the database based on that expression.
Thanks!
The Select(r=>r) does nothing (except change from Table<T> to IQueryable<T> - but nothing useful). And I assume you intended to pass predicate to the Where?
Indeed, this doesn't pull everything out and filter it - the appropriate WHERE (TSQL) clause is generated. This is possible because of "deferred execution" and "composability" - meaning: it doesn't actually execute anything until you start iterating the data (in the ToList()) - until then you are simply shaping the query.
You can see this by doing somthing like:
db.Log = Console.Out;
and look at the TSQL. Or run a TSQL trace. To make it prettier, simplify it to:
return db.Results.Where(predicate).ToList();
I know you said you wanted to pass a predicate and return a List but have you considered returning an IQueryable
Then you could call:
GetResults().Where(r => r.SomeProperty == "SomeValue")
.OrderBy(r => r.SomeOtherProperty)
.Skip(10)
.Take(10); //etc.
With your current API design you would return all records and then have to get 10, where as the above would return only the 10 you needed...
Just some thoughts...