// Building the domain
var domain = BuildDomain();
Key dmitriKey;
int dmitriId;
string dmitriKeyString;
// Opening Session
using (Session.Open(domain)) {
// Opening transaction
using (var transactionScope = Transaction.Open()) {
// Creating user
var dmitri = new User {
Name = "Dmitri"
};
// Storing entity key
dmitriKey = dmitri.Key;
dmitriKeyString = dmitriKey.Format();
dmitriId = dmitri.Id;
Console.WriteLine("Dmitri's Key (human readable): {0}", dmitriKey);
Console.WriteLine("Dmitri's Key (serializable): {0}", dmitriKeyString);
Console.WriteLine("Dmitri's Id: {0}", dmitriId);
// Marking the transaction scope as completed to commit it
transactionScope.Complete();
}
// Opening another transaction
using (var transactionScope = Transaction.Open()) {
// Parses the serialized key
var anotherDimtriKey = Key.Parse(Domain.Current, dmitriKeyString);
// Keys are equal
Assert.AreEqual(dmitriKey, anotherDimtriKey);
// Materialization on fetch
var dmitri = Query<User>.Single(dmitriKey);
// Alternative way to do the same
var anotherDmitri = Query<User>.SingleOrDefault(dmitriKey);
Assert.AreSame(dmitri, anotherDmitri);
// Fetching by key value(s)
anotherDmitri = Query<User>.Single(dmitriId);
Assert.AreSame(dmitri, anotherDmitri);
// Modifying the entity
dmitri.Name = "Dmitri Maximov";
// Opening new nested transaction
using (var nestedScope = Transaction.Open(TransactionOpenMode.New)) {
// Removing the entity
dmitri.Remove();
Assert.IsTrue(dmitri.IsRemoved);
AssertEx.Throws<InvalidOperationException>(() => {
var dmitryName = dmitri.Name;
});
// No nestedScope.Complete(), so nested transaction will be rolled back
}
// Transparent Entity state update
Assert.IsFalse(dmitri.IsRemoved);
Assert.AreEqual("Dmitri Maximov", dmitri.Name);
// Creating few more objects
var xtensiveWebPage = new WebPage {
Title = "Xtensive Web Site",
Url = "http://www.x-tensive.com"
};
var alexYakuninBlogPage = new WebPage {
Title = "Alex Yakunin's Blog",
Url = "http://blog.alexyakunin.com"
};
var subsonicPage = new WebPage {
Title = "SubSonic project page",
Url = "http://www.subsonicproject.com/"
};
// Adding the items to EntitySet
dmitri.FavoritePages.Add(xtensiveWebPage);
dmitri.FavoritePages.Add(alexYakuninBlogPage);
dmitri.FavoritePages.Add(subsonicPage);
// Removing the item from EntitySet
dmitri.FavoritePages.Remove(subsonicPage);
// Getting count of items in EntitySet
Console.WriteLine("Dmitri's favorite page count: {0}", dmitri.FavoritePages.Count);
Assert.AreEqual(2, dmitri.FavoritePages.Count);
Assert.AreEqual(2, dmitri.FavoritePages.Count()); // The same, but by LINQ query
// Enumerating EntitySet
foreach (var page in dmitri.FavoritePages)
Console.WriteLine("Dmitri's favorite page: {0} ({1})", page.Title, page.Url);
// Checking for the containment
Assert.IsTrue(dmitri.FavoritePages.Contains(xtensiveWebPage));
Assert.IsTrue(dmitri.FavoritePages.Contains(alexYakuninBlogPage));
Assert.IsFalse(dmitri.FavoritePages.Contains(subsonicPage));
// Opening new nested transaction
using (var nestedScope = Transaction.Open(TransactionOpenMode.New)) {
// Clearing the EntitySet
dmitri.FavoritePages.Clear();
Assert.IsFalse(dmitri.FavoritePages.Contains(xtensiveWebPage));
Assert.IsFalse(dmitri.FavoritePages.Contains(alexYakuninBlogPage));
Assert.IsFalse(dmitri.FavoritePages.Contains(subsonicPage));
Assert.AreEqual(0, dmitri.FavoritePages.Count);
Assert.AreEqual(0, dmitri.FavoritePages.Count()); // By query
// No nestedScope.Complete(), so nested transaction will be rolled back
}
// Transparent EntitySet state update
Assert.IsTrue(dmitri.FavoritePages.Contains(xtensiveWebPage));
Assert.IsTrue(dmitri.FavoritePages.Contains(alexYakuninBlogPage));
Assert.IsFalse(dmitri.FavoritePages.Contains(subsonicPage));
Assert.AreEqual(2, dmitri.FavoritePages.Count);
Assert.AreEqual(2, dmitri.FavoritePages.Count()); // The same, but by LINQ query
// Finally, let's query the EntitySet:
// Query construction
var dmitryFavoriteBlogs =
from page in dmitri.FavoritePages
where page.Url.ToLower().Contains("blog")
select page;
// Query execution
var dmitryFavoriteBlogList = dmitryFavoriteBlogs.ToList();
// Printing the results
Console.WriteLine("Dmitri's favorite blog count: {0}", dmitryFavoriteBlogList.Count);
foreach (var page in dmitryFavoriteBlogList)
Console.WriteLine("Dmitri's favorite blog: {0} ({1})", page.Title, page.Url);
Assert.IsTrue(dmitryFavoriteBlogList.Contains(alexYakuninBlogPage));
Assert.IsFalse(dmitryFavoriteBlogList.Contains(xtensiveWebPage));
Assert.AreEqual(1, dmitryFavoriteBlogList.Count);
// Marking the transaction scope as completed to commit it
transactionScope.Complete();
}
}
Its output:
Dmitri's Key (human readable): User, (1) Dmitri's Key (serializable): Xtensive.Storage.Manual.EntitySets.TestFixture+User, Xtensive.Storage.Manual, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null: 1 Dmitri's Id: 1 Dmitri's favorite page count: 2 Dmitri's favorite page: Alex Yakunin's Blog (http://blog.alexyakunin.com) Dmitri's favorite page: Xtensive Web Site (http://www.x-tensive.com) Dmitri's favorite blog count: 1 Dmitri's favorite blog: Alex Yakunin's Blog (http://blog.alexyakunin.com)
So Denis Krjuchkov recently has made a great job ;) Nested transactions are fully operable.
Btw, this sample is a kind of "cheat sheet" for basic operations on Entities and EntitySets.
No comments:
Post a Comment