Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

CRUD Operations in ADO.NET Data Services With Custom Provider

DZone's Guide to

CRUD Operations in ADO.NET Data Services With Custom Provider

·
Free Resource

After we learned how to consume an ADO.NET data service with a .Net client in the previous post, the next
thing to learn is how to do CRUD (Create, Update and Delete) operations with the client we built. This post will
explain how to use these operations.

The IUpdatable Interface

In order to enable a a custom provider to do CRUD operations the data context object need to implement the IUpdatable interface. That interface can be found in the System.Data.Services namespace. The interface include a variety of methods to implement and in the example I will show only a couple of those methods.
Returning to the example of the last post, I changed a bit the CoursesDataContext to implement the IUpdatable interface and also to hold a static Course list which will be the object that the data service will use.

The Data Context Example

public class CoursesDataContext : IUpdatable
{
#region Members

private static List<Course> _courses;

#endregion

#region Properties

/// <summary>
/// Return the courses in a IQueryable format
/// </summary>

public IQueryable<Course> Courses
{
get

{
return _courses.AsQueryable();
}
}


#endregion

#region Ctor

/// <summary>
/// Construct a new CoursesDataContext object
/// </summary>

static CoursesDataContext()
{
_courses = Course.GetCourses();
}

#endregion

#region IUpdatable Members

public object CreateResource(string containerName, string fullTypeName)
{
// create the object using reflection
var objType = Type.GetType(fullTypeName);

var resourceToAdd = Activator.CreateInstance(objType);

// add the course to the courses in-memory list
_courses.Add((Course)resourceToAdd);

return resourceToAdd;
}

public void DeleteResource(object targetResource)
{
// remove the course form the courses list
_courses.Remove((Course)targetResource);
}

public object GetResource(IQueryable query, string fullTypeName)
{
object result = null;

var enumerator = query.GetEnumerator();

while (enumerator.MoveNext())
{
if (enumerator.Current != null)
{
result = enumerator.Current;
break;
}
}

if (fullTypeName != null && !fullTypeName.Equals(result.GetType().FullName))
{
throw new DataServiceException();
}

return result;
}

public object GetValue(object targetResource, string propertyName)
{
// get the property info using reflection
var targetType = targetResource.GetType();

var targetProperty = targetType.GetProperty(propertyName);

// retrun the value of the property
return targetProperty.GetValue(targetResource, null);
}

public void SetValue(object targetResource, string propertyName, object propertyValue)
{
// get the property info using reflection
Type targetType = targetResource.GetType();

PropertyInfo property = targetType.GetProperty(propertyName);

// set the property value
property.SetValue(targetResource, propertyValue, null);
}

public object ResolveResource(object resource)
{
// nothing to do just return the resource
return resource;
}

public void SaveChanges()
{
// object in memory - do nothing
}

public void SetReference(object targetResource, string propertyName, object propertyValue)
{
throw new NotImplementedException();
}

public object ResetResource(object resource)
{
throw new NotImplementedException();
}

public void ClearChanges()
{
throw new NotImplementedException();
}

public void AddReferenceToCollection(object targetResource, string propertyName, object resourceToBeAdded)
{
throw new NotImplementedException();
}

public void RemoveReferenceFromCollection(object targetResource, string propertyName, object resourceToBeRemoved)
{
throw new NotImplementedException();
}

#endregion
}

I didn’t implemented the following methods – RemoveReferenceFromCollection, AddReferenceToCollection, ClearChanges, ResetResource and SetReference. The reason is that in my example I don’t use them.

The Calling Method Example

class Program
{
static void Main(string[] args)
{
// build the proxy
var proxy = new CoursesDataContext(new Uri("http://localhost:4205/CoursesService.svc/"));

proxy.MergeOption = MergeOption.AppendOnly;

var CGCourse = new Course
{
CourseID = 4,

Creadit = 5,

Days = 3,

Title = "Computer Graphics"
};

proxy.AddToCourses(CGCourse);

proxy.SaveChanges();


PrintCoursesToConsule(proxy);

CGCourse.Creadit = 3;

proxy.UpdateObject(CGCourse);

proxy.SaveChanges();

PrintCoursesToConsule(proxy);

proxy.DeleteObject(CGCourse);

proxy.SaveChanges();

PrintCoursesToConsule(proxy);

Console.Read();
}

private static void PrintCoursesToConsule(CoursesDataContext proxy)
{

var courses = from course in proxy.Courses select course;

foreach (Course course in courses)
{
Console.WriteLine(

"Course name: {0}, Course duration: {1}, Course credit: {2}",

course.Title,

course.Days,

course.Creadit

);
}

Console.WriteLine();
}

}

Example Revealed

  • Create - when I want to add a new course I use the method AddToCourses of the proxy or AddObject method (which I need to supply the name of the resource which the object will the added to). After the call for one of these method, a call to SaveChanges method will create the object on the data service’s side. The following methods will be called on the data context in the order I use -  CreateResource, SetValue (for every property), SaveChanges and ResolveResource. In the CreateResource method I use the fullTypeName parameter to create the type with reflection, add it to the courses list and return it as the created object. The SetValue method will be called for every
    property of the object and set all them also using reflection. SaveChanges is an empty method which do nothing because we are using an in-memory object. ResolveResource return the object it get because we don’t need to resolve anything.
  • Update – when we want to update an existing object we call the UpdateObject method of the proxy class. After that call the call to SaveChanges will pass the request to the data context. The methods that will be called on the data context will be – GetResource, SetValue, SaveChanges and ResolveResource. The GetResource gets a IQueryable query which holds the data to update. I extract the resource to update and return it. The other methods where explained in the create bullet.
  • Delete – in order to the delete an object I use the DeleteObject method followed by the  SaveChanges method. The chain of method that will be called on the data  context will be – GetResource, DeleteResource, SaveChanges and ResolveResource. The only method that concerns us (all the other where explain earlier) is the DeleteResource method that only removes the object it gets from the courses list.

Summary

Lets sum up the post, in order to use CRUD operations in a custom provider of a data service you need to implement the IUpdatable interface. I provided an example of how to implement a simple data context and I hope it will help you to build your own. In the next post in the ADO.NET data services I’ll write about how to perform batch operations.

Topics:

Published at DZone with permission of Gil Fink, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}