Mike Taulty's Blog
Bits and Bytes from Microsoft UK
ADO.NET Data Services - Exposing Arbitrary Data (2)

Blogs

Mike Taulty's Blog

Elsewhere

Following on from the previous post, I wanted to look at how we can make our arbitrary data source available for both read and write in the same way that an Entity Framework data source is.

As I talked about in this post, this involves implementing IUpdatable on the class that we feed to WebDataService<T>. IUpdatable looks like this;

image

 

Inserting Data

With my Entity Framework based data-source I can perform a simple insert with code such as;

demoEntities efService = new demoEntities("http://localhost:32767/WebSite6/EFService.svc");
      efService.MergeOption = Microsoft.Data.WebClient.MergeOption.AppendOnly;

      author a = new author()
      {
        id = 4,
        firstName = "Joseph",
        lastName = "Heller"
      };

      efService.AddObject("author", a);
      efService.SaveChanges();

If I want to be able to do this with my in-memory service then I need to implement IUpdatable.Add and IUpdatable.SaveChanges. I implemented them like this on my BookContext class which I posted in the previous post.

    public void Add(object resource, string containerName)
    {
      switch (containerName)
      {
        case "Books":
          Add((Book)resource);
          break;
        case "Authors":
          Add((Author)resource);
          break;
        default:
          Debug.Assert(false);
          break;
      }
    }
    public void SaveChanges()
    {
      // We do nothing, our data is in memory
    }
    private static void Add<T>(T resource)
    {
      CollectionInfo ci = collections[typeof(T)];
      try
      {
        ci.Lock.AcquireWriterLock(-1);
        List<T> list = (List<T>)ci.List;
        list.Add(resource);
      }
      finally
      {
        ci.Lock.ReleaseWriterLock();
      }
    }

And now I can write the same sort of client code against my in-memory data source as I did against the Entity Framework based data source;

      BookContext memService = new BookContext("http://localhost:32767/WebSite6/MemoryService.svc");
      memService.MergeOption = Microsoft.Data.WebClient.MergeOption.AppendOnly;

      Author mA = new Author()
      {
        ID = 4,
        FirstName = "Joseph",
        LastName = "Heller"
      };
      memService.AddObject("Authors", mA);
      memService.SaveChanges();

It might be, that I want to be able to insert an Author and their book at the same time. Against the Entity Framework data source I can write;

      // EF Service
      demoEntities efService = new demoEntities("http://localhost:32767/WebSite6/EFService.svc");
      efService.MergeOption = Microsoft.Data.WebClient.MergeOption.AppendOnly;

      author lee = new author()
      {
        id = 5,
        firstName = "Harper",
        lastName = "Lee"
      };

      efService.AddObject("author", lee);

      book book = new book()
      {
        id = 5,
        title = "To Kill a Mockingbird",
        price = 4.99m,
        author = lee
      };
      
      efService.AddObject("book", book);
      efService.AddBinding(book, "author", lee);

      efService.SaveChanges();

I'm not 100% sure that there shouldn't also be a call in there which looks like this;

efService.AddBinding(author, "book", book);

To do that with my in-memory model means implementing more of IUpdatable and so I added Attach and AddResourceToCollection to my existing BookContext class in order to try and make that work;

    public object Attach(Type resourceType, 
      IEnumerable<KeyValuePair<string, object>> keyValues, 
      string containerName)
    {
      // No notion of attaching, everything is in memory so find the
      // right object and return it.
      int key = 
        (from pair in keyValues where pair.Key == "ID" select (int)pair.Value).Single();

      object attachedObject = null;

      CollectionInfo ci = collections[resourceType];      

      try
      {
        ci.Lock.AcquireReaderLock(-1);

        IEnumerable<KeyedEntity> list = ((IList)ci.List).OfType<KeyedEntity>();

        attachedObject = 
          (from entry in list where entry.ID == key select entry).Single();
      }
      finally
      {
        ci.Lock.ReleaseReaderLock();
      }
      return (attachedObject);
    }

and then the second function;

    public void AddResourceToCollection(object propertyValue, 
      System.Reflection.PropertyInfo propertyInfo, 
      object resourceToBeAdded, 
      bool update)
    {
      IList list = (IList)propertyValue;

      // We assume the list is thread-safe.
      list.Add(resourceToBeAdded);
    }
and then I can write client-side code against this such as;
   BookContext memService = new BookContext("http://localhost:32767/WebSite6/MemoryService.svc");
      memService.MergeOption = Microsoft.Data.WebClient.MergeOption.AppendOnly;

      Author lee = new Author()
      {
        ID = 5,
        FirstName = "Harper",
        LastName = "Lee"
      };

      memService.AddObject("Authors", lee);

      Book book = new Book()
      {
        ID = 5,
        Title = "To Kill a Mockingbird",
        Price = 4.99m,
        Author = lee
      };

      memService.AddObject("Books", book);
      memService.AddBinding(book, "Author", lee);
      memService.AddBinding(lee, "Books", book);

      memService.SaveChanges();

which "seems" to work ok in that I can revisit the service and query it to see my new author and their new book and navigate from one entity to the other.

This post is getting long so I'll follow up with another post about deleting data and updating data.


Posted Thu, Jan 3 2008 3:38 AM by mtaulty

Comments

Mike Taulty's Blog wrote ADO.NET Data Services - Exposing Arbitrary Data (3)
on Thu, Jan 3 2008 3:53 AM
Following on from these posts;  ADO.NET Data Services - Exposing Arbitrary Data (1)  ADO.NET Data Services...
Mike Taulty's Blog wrote ADO.NET Data Services - Exposing Arbitrary Data (4)
on Thu, Jan 3 2008 4:00 AM
Following on from these posts;  ADO.NET Data Services - Exposing Arbitrary Data (1) ADO.NET Data Services...
Noticias externas wrote DP 关注之一(2008/01/09)
on Wed, Jan 9 2008 12:55 AM