Count submitted queries - linq-to-sql

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.

Related

Trying to restrict an Eloquent query to a relationship with a count of 0

I have two models (Organizations and Interactions) and I'd like to query the Organization model for all of the Orgs that have no Interactions. Organizations have a one-to-many relationship with Interactions.
I tried looking into anti-joins in raw SQL, but got nowhere. I also wanted to totally avoid anything like getting all of the full Organizations, then iterating through them to check to see if they had any Interactions, because that's completely impractical given the amount of data I'm working with.
To clarify, I want to avoid this:
$organizations = Organization::all();
foreach ($organizations as $org)
if($org->interactions()->count() == 0){
//Add the org to an array for later use because it has no interactions
}
I'm using Laravel 3.x, and I can't upgrade because the project is really big and I don't have the month it would take to upgrade to 4.1 right now. If there's a significantly better way to do stuff like this 4, that would make selling the conversion process easier.
Here's some relevant code:
//From organization.php
public function interactions() {
return $this->has_many('Interaction');
}
//From interaction.php
public function organization() {
return $this->belongs_to('Organization');
}
// select all Organization IDs that have at least 1 interaction
$uniqueOrganizationIDs = DB::raw('SELECT organization_id FROM interactions GROUP BY(organization_id)');
// Select orgs that were not in the above list.
Organization::whereNotIn('id', $uniqueOrganizationIDs)->get();
This is the solution I came up with:
Query the Organization and Interaction models using list(). For Orgs, get their ID. For Interactions, get their organization_id. I figure these are two low-footprint, fast queries.
Do an array_diff() on them to get an array of Organizations that don't have Interactions.
Query Organization using where_in(), feeding it the diff'ed array.
It looks like this:
$organizationIDs = DB::table('organizations')->where('is_deleted', '=', 0)->lists('id');
$interactionIDs = DB::table('interactions')where('is_deleted', '=', 0)->lists('organization_id');
$uncontactedOrganizationIDs = array_diff($organizationIDs, $interactionIDs);
$uncontactedOrganizations = Organization::where_in('id', $uncontactedOrganizationIDs)->order_by('created_at', 'DESC')->get();
Is there a better way to do this? I feel like there has to be.

How IQueryables are dealt with in ASP.NET MVC Views?

I have some tables in a MySQL database to represent records from a sensor. One of the features of the system I'm developing is to display this records from the database to the web user, so I used ADO.NET Entity Data Model to create an ORM, used Linq to SQL to get the data from the database, and stored them in a ViewModel I designed, so I can display it using MVCContrib Grid Helper:
public IQueryable<TrendSignalRecord> GetTrends()
{
var dataContext = new SmgerEntities();
var trendSignalRecords = from e in dataContext.TrendSignalRecords
select e;
return trendSignalRecords;
}
public IQueryable<TrendRecordViewModel> GetTrendsProjected()
{
var projectedTrendRecords = from t in GetTrends()
select new TrendRecordViewModel
{
TrendID = t.ID,
TrendName = t.TrendSignalSetting.Name,
GeneratingUnitID = t.TrendSignalSetting.TrendSetting.GeneratingUnit_ID,
//{...}
Unit = t.TrendSignalSetting.Unit
};
return projectedTrendRecords;
}
I call the GetTrendsProjectedMethod and then I use Linq to SQL to select only the records I want. It is working fine in my developing scenario, but when I test it in a real scenario, where the number of records is way greater (something around a million records), it stops working.
I put some debug messages to test it, and everything works fine, but when it reaches the return View() statement, it simply stops, throwing me a MySQLException: Timeout expired. That let me wondering if the data I sent to the page is retrieved by the page itself (it only search for the displayed items in the database when the page itself needs it, or something like that).
All of my other pages use the same set of tools: MVCContrib Grid Helper, ADO.NET, Linq to SQL, MySQL, and everything else works alright.
You absolutely should paginate your data set before executing your query if you have millions of records. This could be done using the .Skip and .Take extension methods. And those should be called before running any query against your database.
Trying to fetch millions of records from a database without pagination would very likely cause a timeout at best.
Well, assuming information in this blog is correct, .AsPagination method requires you to sort your data by a particular column. It's possible that trying to do an OrderBy on a table with millions of records in it is just a time consuming operation and times out.

LINQ Dynamic WHERE but Clean Special Chars first

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.

IQueryable, Where, Guid and

I'm working my way through the MVC Storefront code and trying to follow the path of a repository, a service and a model that is a poco, outside of the dbml/data context. It's pretty easy to follow actually, until I started writing tests and things failed in a way I just don't understand.
In my case, the primary key is a uniqueidentifier instead of an int field. The repository returns an IQueryable:
public IQueryable<Restaurant> All()
{
return from r in _context.Restaurants select new Restaurant(r.Id)
{
Name = r.Name
};
}
In this case, Restaurant is a Models.Restaurant of course, and not _context.Restaurants.Restaurant.
Filtering in the service class (or in repository unit tests) against All(), this works just as expected:
var results = Repository.All().Where(r => r.Name == "BW<3").ToList();
This works just fine, has one Model.Restaurant. Now, if I try the same things with the pkid:
var results = Repository.All().Where(r => r.Id == new Guid("088ec7f4-63e8-4e3a-902f-fc6240df0a4b")).ToList();
If fails with:
The member 'BurningPlate.Models.Restaurant.Id' has no supported translation to SQL.
If seen some similiar posts where people say it's because r => r.Id is [Model.Restaurants] is a class level the linq2sql layer isn't aware of. To me, that means the the first version shouldn't work either. Of course, if my pk is an int, it works just fine.
What's really going on here? Lord knows, it's not very intuitive to have one work and one not work. What am I misunderstanding?
I think the problem here is due to using a constructor overload, and expecting the query to fill it in. When you do a projection like this, you have to put all the things you want to be in the projection query in the actual projection itself. Otherwise Linq won't include that in the SQL query.
So, rewrite your bits like so:
return from r in _context.Restaurants select new Restaurant()
{
Id=r.Id,
Name = r.Name
};
This should fix it up.
Not having actually typed this code out, have you tried
var results = Repository.All().Where(r => r.Id.Equals(new Guid("088ec7f4-63e8-4e3a-902f-fc6240df0a4b")).ToList()
Ninja
this probably has to do with fact that you trying to instantiate the guid in the query, and I think that LINQ to SQL is trying to convert that to actual SQL code before the object is created.
Try instantiating before the query and not on the query.

Linq to SQL - Underlying Column Length

I've been using Linq to SQL for some time now and I find it to be really helpful and easy to use. With other ORM tools I've used in the past, the entity object filled from the database normally has a property indicating the length of the underlying data column in the database. This is helpful in databinding situations where you can set the MaxLength property on a textbox, for example, to limit the length of input entered by the user.
I cannot find a way using Linq to SQL to obtain the length of an underlying data column. Does anyone know of a way to do this? Help please.
Using the LINQ ColumnAttribute to Get Field Lengths from your Database :
http://www.codeproject.com/KB/cs/LinqColumnAttributeTricks.aspx
Thanks. Actually both of these answers seem to work. Unfortunately, they seem to look at the Linq attributes generated when the code-generation was done. Although that would seem to be the right thing to do, in my situation we sell software products and occasionally the customer will expand some columns lengths to accommodate their data. Thus, the length of the field as reported using this technique may not always reflect the true length of the underlying data column. Ah well, not Linq to SQL's fault, is it? :)
Thanks for the quick answers!
If you need to know the exact column length you can resort to the System.Data classes themselves. Something a bit like this:
var context = new DataContextFromSomewhere();
var connection = context.Connection;
var command = connection.CreateCommand( "SELECT TOP 1 * FROM TableImInterestedIn" );
var reader = command.ExecuteReader();
var table = reader.GetSchemaTable();
foreach( var column in table.Columns )
{
Console.WriteLine( "Length: {0}", column.MaxLength );
}