In this example we demonstrate use of immutable data in the data model.

We use the ImmutableAttribute (see Attributes) in the data model to define that relation from Order to Product will not be affected by later changes to the product, such as price. This means that order will always stay with the original price and other product information:
    public interface IProduct
    {
        string Name { get; set; }
        int Price { get; set; }
    }

    public interface IOrder
    {
        DateTime Date { get; set; }
        
        [Immutable]
        IUser User { get; set; }

        [Immutable]
        IProduct Product { get; set; }
    }

    public interface IUser
    {
        string Username { get; set; }
        int Age { get; set; }
    }

    public interface IDataModel
    {
        ICollection<IUser> Users { get; set; }
        ICollection<IProduct> Products { get; set; }
        ICollection<IOrder> Orders { get; set; }
    }


First we create all the data, choosing a flat file IndexedFileStorage as storage:
            var file = new FileStream("data.dat", FileMode.OpenOrCreate);
            var storage = new IndexedFileStorage(file, 256, true);
            Context ctx = new Context(typeof(IDataModel), null, storage);

            // Initialize data for the first time creating 100 users and 100 products
            using (var ws = ctx.OpenWorkspace<IDataModel>(IsolationLevel.Exclusive))
            {
                if (ws.Data.Users == null)
                {
                    Console.WriteLine("Creating data for the first time");

                    // Create 100 users
                    ws.Data.Users = ws.New<ICollection<IUser>>();
                    for (int i = 0; i < 100; i++)
                    {
                        IUser usr = ws.New<IUser>();
                        usr.Username = "User" + i;
                        usr.Age = i;

                        ws.Data.Users.Add(usr);
                    }

                    //Create 100 products
                    ws.Data.Products = ws.New<ICollection<IProduct>>();
                    for (int i = 0; i < 100; i++)
                    {
                        IProduct prd = ws.New<IProduct>();
                        prd.Name = "Product" + i;
                        prd.Price = i;

                        ws.Data.Products.Add(prd);
                    }

                    // Create 100 orders
                    ws.Data.Orders = ws.New<ICollection<IOrder>>();
                    for (int i = 0; i < 100; i++)
                    {
                        // Use LINQ to find user with appropriate age
                        var user = ws.Data.Users.Single(u => u.Age == i);

                        // Use LINQ to find product with appropriate price
                        var product = ws.Data.Products.Single(p => p.Price.Equals(i));

                        var order = ws.New<IOrder>();
                        order.Date = DateTime.UtcNow;
                        order.Product = product;
                        order.User = user;

                        ws.Data.Orders.Add(order);
                    }

                    ws.Commit();
                }
                else
                {
                    Console.WriteLine("Using data from file");
                }
            }


And then, we decide that all products in the catalog are free:
using (var ws = ctx.OpenWorkspace<IDataModel>(IsolationLevel.Exclusive))
{
  foreach (var product in ws.Data.Products)
  {
    product.Price = 0;
  }

  ws.Commit();
}       


But, when we query through the orders, we find that orders still refer to products with old prices, because it is set to be "Immutable" in the data model:
            using (var ws = ctx.OpenWorkspace<IDataModel>(IsolationLevel.ReadOnly))
            {
                // We list all products with prices
                Console.WriteLine("Product\tPrice");
                foreach (var item in ws.Data.Products)
                {
                    Console.WriteLine("{0}\t{1}", item.Name, item.Price);
                }

                var orders = ws.Data.Orders.Where(o => o.User.Age > 75);
                Console.WriteLine("Date\tProduct\tUser\tPrice");
                foreach (var item in orders)
                {
                    Console.WriteLine("{0}\t{1}\t{2}\t{3}", item.Date, item.Product.Name, item.User.Username, 
                    item.Product.Price);
                }
            }


Additionally, if we tried to change data via order.Product.Price it would report an error! All immutable data is read only.

Full source code for this example can be found in Execom.IOG.ImmutableDB project in project source code.

Last edited Mar 14, 2012 at 11:18 AM by nenadsabo, version 5

Comments

No comments yet.