Deflated References

Thong Nguyen edited this page Mar 29, 2016 · 8 revisions

Deflated References

Deflated References are a powerful and unique feature of Shaolinq. They allow you to:

  • Update objects in a single trip to the database (no read-first required)
  • Access primary keys of related objects in an object-oriented fashion without requiring an extra query
  • Set relationships without requiring any extra queries
  • Query for objects with complex primary keys (primary keys where the primary key is made up of other Data Access Objects) without having to first query the objects that make up the complex primary key

Create a deflated reference

You can create a deflated reference by using the GetReference method available on DataAccessObjects and RelatedDataAccessObjects objects.

var book = model.Books.GetReference(bookId);

If you're using a composite primary key you can pass in an anonymous type

var book = model.AdvancedBooks.GetReference(new { BookId = bookId, LocationId = location Id });

If you have DAOs with primary keys that are themselves DAOs then you can recursively use GetReference:

var book = model.SuperAdvancedBooks.GetReference(new { Title = title, Author = model.Authors.GetReference(new { Id = authorId, Name = authorName }));

Object Inflation

All properties except primary keys on deflated references a write-only until they've been written to once. If you try to read a non-primary key property the entire object will be implicitly Inflated.

var book = model.Books.GetReference(bookId);
var s = book.Title; // Implicit inflation on access to non-PrimaryKey
SELECT T1.Id, T1.Title FROM Book as T1;

You can also explicitly inflate an object by calling the Inflate extension method on DataAccessObject.

var book = model.Books.GetReference(bookId);
var s = book.Inflate(); // SQL
SELECT T1.Id, T1.Title FROM Book as T1;

Because Shaolinq maintains object identity within a single transaction, querying for the same object will cause the original reference to be inflated.

var book = model.Books.GetReference(bookId);
var sameBook = model.Books.Single(c => c.Id == bookId);
Assert.IsTrue(object.ReferenceEquals(book, sameBook)); 
SELECT T1.Id, T1.Title FROM Book as T1;

If you were to inflate an object that uses a complex primary key (primary keys made of one or more DAOs), you can see the SQL generated is well formed:

var book = model.SuperAdvancedBooks.GetReference(new { Title = title, Author = model.Authors.GetReference(new { Id = authorId, Name = authorName }));
book.Inflate();
SELECT Id, Title, AuthorId, AuthorName FROM SuperAdvancedBooks WHERE Title = title AND AuthorId = authorId AND AuthorName = authorName;

Updating an object in a single trip

Because deflated references look exactly like normal objects and can be written to, it's easy to do a single-trip update to an object if you know its primary key.

using (var scope = new DataAccessScope)
{
    var book = model.Books.GetReference(bookId);
    book.Title = "Hello";
    scope.Complete();
}
UPDATE Book SET T1.Title="Hello" WHERE Book.Id = bookId;