0
votes

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?

2

2 Answers

2
votes

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.

0
votes

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