I want to fetch from my DB all requirements related to a given project(in this case currentProject)
I've just used two ways to do this
first one :
Requirement.withCriteria {....
eq("project", currentProject)
...
}
I note that this query doesn't use equals method of Project class, but this query returns me exactly what I want.
second
Requirement.withCriteria {
....
currentProject == property('Project')
...
}
This query use equals method to compare two projects, but I could not overwrite equals method that a exception has been thrown saying "grails can't cast hibernateBuild to domain"
So, I wonder know what the difference between those two queries ?
Thanks to all!
withCriteria method goes to the Database to fetch your entities.
On the database level there is no concept of equals (DB does not know anything about Java). First query gives you the right results because it compares the DB mapping (PRIMARY / FOREIGN keys).
As for the second query - I do not advice to use it. If it uses equals, when it fetches all projects from the DB into memory. And that is a really bad idea.
Related
I am trying to use SharkORM to fetch relationships across my objects. I am familiar with the joinTo syntax defined in SharkORM's documentation, but I am not sure how to use the resulting joinedResults object to get the related objects I need.
[[Person query] joinTo:[Department class] leftParameter:#"department" targetParameter:#"Id"]
outputs
{
"Department.Id" = 61;
"Department.location" = 35;
"Department.name" = Development;
}
into the Person.joinedResults field, but how do I take those results and get a Department object back. I've tried making a call to person.department after the joinTo, but it seems to make a second query to the database as if I hadn't used joinTo at all.
Am I really expected to parse the dictionary results of person.joinedResults into a Department object manually? That is very cumbersome, especially when you start joining more than one relationship.
I feel as if I am missing some obvious way to use the results of the joinTo.
The join functionality is in addition to relationships. So you can reference unrelated (or related) tables in a query, but then objects you get back can only ever be physically structured as per your original class, and are defined from the data and not from your query.
So, in a nut shell; joinTo: will enable you to reference remote or unrelated objects in your query for selection.
But to traverse object relationships you would use the properties.
Person* p = GetFirstPerson()
// reference/traverse the object to look at relationships (1:1)
p.department
or
p.department.location
So I guess what i'm saying is, even though it is SQL like syntax, you can only ever end up with rigidly defined classes in a fixed structure as a result unless using other interfaces such as sum, distinct etc..
I'm looking for a method that is faster and uses less server processing. In my application, I can use both .where and .detect:
Where:
User.where(id: 1)
# User Load (0.5ms)
Detect:
User.all.detect{ |u| u.id == 1 }
# User Load (0.7ms). Sometimes increases more than .where
I understand that .detect returns the first item in the list for which the block returns TRUE but how does it compares with .where if I have thousands of Users?
Edited for clarity.
.where is used in this example because I may not query for the id alone. What if I have a table column called "name"?
In this example
User.find(1) # or
User.find_by(id: 1)
will be the fastest solutions. Because both queries tell the database to return exactly one record with a matching id. As soon as the database finds a matching record, it doesn't look further but returns that one record immediately.
Whereas
User.where(id: 1)
would return an array of objects matching the condition. That means: After a matching record was found the database would continue looking for other records to match the query and therefore always scan the whole database table. In this case – since id is very likely a column with unique values – it would return an array with only one instance.
In opposite to
User.all.detect { |u| u.id == 1 }
that would load all users from the database. This will result in loading thousands of users into memory, building ActiveRecord instances, iterating over that array and then throwing away all records that do not match the condition. This will be very slow compared to just loading matching records from the database.
Database management systems are optimized to run selection queries and you can improve their ability to do so by designing a useful schema and adding appropriate indexes. Every record loaded from the database will need to be translated into an instance of ActiveRecord and will consume memory - both operations are not for free. Therefore the rule of thumb should be: Whenever possible run queries directly in the database instead of in Ruby.
NB One should use ActiveRecord#find in this particular case, please refer to the answer by #spickermann instead.
User.where is executed on DB level, returning one record.
User.all.detect will return all the records to the application, and only then iterate through on ruby level.
That said, one must use where. The former is resistant to an amount of records, there might be billions and the execution time / memory consumption would be nearly the same (O(1).) The latter might even fail on billions of records.
Here's a general guide:
Use .find(id) whenever you are looking for a unique record. You can use something like .find_by_email(email) or .find_by_name(name) or similar (these finders methods are automatically generated) when searching non-ID fields, as long as there is only one record with that particular value.
Use .where(...).limit(1) if your query is too complex for a .find_by query or you need to use ordering but you are still certain that you only want one record to be returned.
Use .where(...) when retrieving multiple records.
Use .detect only if you cannot avoid it. Typical use cases for .detect are on non-ActiveRecord enumerables, or when you have a set of records but are unable to write the matching condition in SQL (e.g. if it involves a complex function). As .detect is the slowest, make sure that before calling .detect you have used SQL to narrow down the query as much as possible. Ditto for .any? and other enumerable methods. Just because they are available for ActiveRecord objects doesn't mean that they are a good idea to use ;)
I was trying to figure out how the DataContext.ObjectTrackingEnabled property works in F# SQL Type Provider. Unfortunatelly I don't find any useful documentation except this msdn entry which is unhelpful too.
Shouldn't the object tracking feature, track all the objects loaded inside the same "session/context"? Let's say I query for an object, it gets loaded to the "context" and if I query for the same object once again in the same "context" it should load it from the context without executing SQL statement in RDBMs?
This code results in two SQL queries. I was expected to see only one in SQL Server Profiler:
[<Literal>]
let connectionString = #"server=localhost;database=..."
type dbSchema = SqlDataConnection<ConnectionString=connectionString>
let db = dbSchema.GetDataContext(connectionString)
let result = (query
{
for t in db.Table1 do
where (t.Id = 1)
select t
}).SingleOrDefault()
let result2 = (query
{
for t in db.Table1 do
where (t.Id = 1)
select t
}).SingleOrDefault()
What do I miss?
This is really a property of the LINQ to SQL framework, so it shouldn't be specific to F# (and so finding more about object tracking in LINQ to SQL should answer the question).
I'm not really a LINQ to SQL expert, but my understanding of this feature is that having ObjectTrackingEnabled = true does not avoid running multiple queries to retrieve the data. What it does is that it ensures that the queries return the same .NET objects representing the entities.
This means that if you have two queries that return the same entitiy and you modify a property of one of the entity (before you commit the change to the database), this will also change the property of the entity returned by the other query (because they're the same object).
In contrast, if you disable this and run two queries, they both return new .NET objects with values exactly as in the database. If your program modifies one of the objects, it will not affect the other (and so if you try to commit changes to the DB using both entities, you'll get a conflict).
In summary - disabling this gives you better performance if you're just reading data (because there is less tracking overhead), but it might be inappropriate if you want to edit the objects in your application and save data back to the database.
As Tomas said this is not directly related to the Type Provider but to the underlying LINQ to SQL implementation. But many F# developers use those providers, so a little history on Linq to SQL would be useful.
In general ObjectTrackingEnabled = true avoid running multiple queries to retrieve the data under the following conditions :
In general, for a LINQ to SQL query to return an object from the
identity cache, the query must be based on the primary key of an
object and must return a single object.
so in where(predicate) predicate must be an expression in which the object's primary key property is set to a constant value. If an object has a primary key defined by more than one property, each primary key property must be set to a constant value. The following are examples of the form predicate must take:
c => c.PK1 == constant_value1 && c=> c.PK2 == constant_value2
This information is taken from MSDN
My objective:
I have built a working controller action in MVC which takes user input for various filter criteria and, using PredicateBuilder (part of LinqKit - sorry, I'm not allowed enough links yet) builds the appropriate LINQ query to return rows from a "master" table in SQL with a couple hundred thousand records. My implementation of the predicates is totally inelegant, as I'm new to a lot of this, and under a very tight deadline, but it did make life easier. The page operates perfectly as-is.
To this, I need to add a Full-Text search filter. Understanding the way LINQ translates Contains to LIKE(%%), using the advice in Simon Blog: LINQ-to-SQL - Enabling Full-Text Searching, I've already prepared Table Functions in SQL to run Freetext queries on the relevant columns. I have 4 functions, to match the query against 4 separate tables.
My approach:
At the moment, I'm building the predicates (I'll spare you) for the initial IQueryable data object, running a LINQ command to return them, like so:
var MyData = DB.Master_Items.Where(outer);
Then, I'm attempting to further filter MyData on the Keys returned by my full-text search functions:
var FTS_Matches_Subtable_1 = (from tbl in DB.Subtable_1
join fts in DB.udf_Subtable_1_FTSearch(KeywordTerms)
on tbl.ID equals fts.ID
select tbl.ForeignKey);
... I have 4 of those sets of matches which I've tried to use to filter my original dataset in several ways with no success. For instance:
MyNewData = MyData.Where(d => FTS_Matches_Subtable_1.Contains(d.Key) ||
FTS_Matches_Subtable_2.Contains(d.Key) ||
FTS_Matches_Subtable_3.Contains(d.Key) ||
FTS_Matches_Subtable_4.Contains(d.Key));
I just get the error: The incoming tabular data stream (TDS) remote procedure call (RPC) protocol stream is incorrect. Too many parameters were provided in this RPC request. The maximum is 2100.
I get that it's because I'm trying to pass a relatively large set of data into the Contains function and LINQ is converting each record into a separate parameter, exceeding the limit.
I just don't know how to get around it.
I found another post linq expression to return property value which seemed SO promising. I tried ifwdev's solution (2nd highest ranked answer): using LinqKit to build an extension that will break up the queries into manageable chunks. But I can't figure out how to implement it. Out of my depth right now maybe?
Is there another approach that I'm missing? Some simpler way to accomplish this that I've overlooked?
Sorry for the long post. But thank you for any help you can provide!
This is a perfect time to go back to raw ado.net.
Twisting things around just to use linq to sql is probably just as time consuming if you wrote the query and hydration by hand.
I'm a beginner at rails. And I've come to understand two different ways to return the same result.
What is the difference between these two? And what situation would require you to choose one from the other?
Example 1:
Object.find(:all).select {|c| c.name == "Foobar" }.size
Example 2:
Object.count(:conditions => ['name = ?', 'Foobar'])
FURTHER NOTE:
I seriously wish I could vote everyone correct answers for this one. Thank you so much. I just had a serious rails affirmation.
Object.count always hits the DB, and the find()....size() call can optimize. Good discussion here
http://rhnh.net/2007/09/26/counting-activerecord-associations-count-size-or-length
Example 1:
This constructs a query:
SELECT * FROM objects
then turns all the records into a collection of objects in your memory, then iterates through every object to see if it meets the condition, and then counts the number of elements that meet condition.
Example 2:
This constructs a query:
SELECT count(id) FROM objects WHERE name = 'Foobar'
lets sql do all the hard work, and returns just an integer - a number of objects meeting condition.
Usually you want no 2 - faster and less memory
Example 1 will load all of your records from the DB (assuming Object is an ActiveRecord model), then uses Ruby to reduce the set, and then return the size of that array. So this is potentially memory and CPU heavy - not good.
Example 2 performs the count in SQL, so all the heavy lifting is performed in the database, not in Ruby. Much better :)
In example 1, you are getting all objects from the datastore, and then iterating over all of them, selecting the objects that has the name Foobar. And then getting the size of that array. Example 1 is the clear loser here.
Example 1 sql:
select * from whatever
# then iterate over entire array
Example two executes a where clause in SQL to the datastore.
select count(id) from whatever where name = 'foobar'
# The SQL above is sql-server accurate, but not necessarily mysql or sqlite3