DCSIMG
November 2008 - Posts - Gil Fink's Blog

Gil Fink's Blog

Fink about IT

News

Microsoft MVP

My Facebook Profile My Twitter Profile My Linkedin Profile

Locations of visitors to this page

Creative Commons License

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.
© Copyright 2013 Gil Fink

Hebrew Articles

Index Pages

My OSS Projects

English Articles

November 2008 - Posts

ADO.NET Data Services Session

ADO.NET Data Services Session

The reason why I didn’t ADO.NET Data Services Session
write posts in the last week
was revealed two days ago.
I’m preparing for an ADO.NET Data
Services session
which will
occur on Wednesday, 3.12 in the Israel VB
User Group
. You can register the event here.

ADO.NET Data Services Webcasts

ADO.NET Data Services Webcasts

Mike Taulty, from the Developer ADO.NET Data Services Webcasts
and Platform Group at Microsoft
in the UK, has published a 
series of webcasts to help
developers getting started
with the ADO.NET data Services
world. You can watch the webcasts from here:

Enjoy.

Dependency Injection From Theory to Practice With Unity Article

Dependency Injection From Theory to Practice With Unity Article

Today my article, Dependency Dependency Injection From Theory to Practice With Unity
Injection From Theory to Practice With Unity
,
was published on the Hebrew MSDN site.
The article describe what is dependency injection
and then introduce the Unity application block.
You can read the article here.
You can read more Hebrew MSDN articles here.

Enjoy.

Consuming Data Services Service Operations

Consuming Data Services Service Operations

In the following post Consuming Data Services Service Operations
I’m going to explain
how to consume
ADO.NET data services
service operations
from
your clients.

The Problem

In my previous post I introduced the concept of service operations
in ADO.NET data services. After adding a service reference in my client
application a problem raised it head. The service operations aren’t exposed
in the generated proxy. Probably this feature will be added in the future
by the ADO.NET team (I hope). Meanwhile, we need a solution to help us
consume the service operations (or else why should we use them).

Solving The Problem – Consuming Service Operations

The generated DataServiceContext holds the keys to solve the service operations
consuming problem. There are three methods that we can use in order to use
the service operation we built:

  • CreateQuery – which create a data service query.
  • Execute – which is used to query a data service by URI.
  • BeginExecute – which do the same as Execute but asynchronously.

CreateQuery Example

The following code demonstrate the use of CreateQuery to run the
service operation we built in the previous post:

// build the proxy

var proxy = new CoursesDataContext(

        new Uri("http://localhost:4205/CoursesService.svc/"));

// create a query with a the credits argument

var courses = proxy.CreateQuery<Course>("CoursesByCredits")

    .AddQueryOption("credits", 3);

// write to console the results

foreach (var course in courses)

{

    Console.WriteLine(

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

        course.Title,

        course.Days,

        course.Credits

    );

}

as you can see I create a query with the operation name and attach
to it the credits argument.

Execute Example

The following code demonstrate the use of the Execute method in order to
run the service operation:

// build the proxy

var proxy = new CoursesDataContext(

        new Uri("http://localhost:4205/CoursesService.svc/"));


// execute the service operation

var courses = proxy.Execute<Course>(

    new Uri(string.Format("{0}CoursesByCredits?credit={1}",
                          proxy.BaseUri, 3),

            UriKind.RelativeOrAbsolute));

// write to console the results

foreach (var course in courses)

{

    Console.WriteLine(

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

        course.Title,

        course.Days,

        course.Credit

    );

}

In the use of the Execute method I need to supply the URI of the
operation. The method returns an IEnumerable collection.

BeginExecute Example

The following code demonstrate the use of the BeginExecute method in order
to run the service operation:

// build the proxy

var proxy = new CoursesDataContext(

        new Uri("http://localhost:4205/CoursesService.svc/"));

// execute the query asynchronously
proxy.BeginExecute<Course>(

          new Uri(string.Format("{0}CoursesByCredits?credit={1}",
                                proxy.BaseUri, 3),

                  UriKind.RelativeOrAbsolute),

          OnQueryComplete, null);

The case of BeginExecute method is very similar to the Execute method
but we need to supply a callback function which in my example is called
OnQueryComplete:

private void OnQueryComplete(IAsyncResult result)

{

    IQueryable<Course> queryResults =

        proxy.EndExecute<Course>(result).AsQueryable();

    foreach (var course in queryResults)

    {

        Console.WriteLine(

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

            course.Title,

            course.Days,

            course.Credit

            );

    }

}

Summary

Lets sum up, I showed how to consume a service operation from
a .Net client. I really hope that the ADO.NET team will expose the
service operations from the generated proxy when we add a service
reference to our applications. If they wont do that I gave you three ways
to consume service operations in the post.

Service Operations – Adding Business Logic to a Data Service

Service Operations – Adding Business Logic to a Data Service

In the following post Service Operations – Adding Business Logic to a Data Service
I’m going to explain
what are service operations
and how to use them to
add business logic to an 
ADO.NET data services.

What are Service Operations?

ADO.NET Data Services enable definition of service operations to
extend the model of mapping URIs to resources. This feature can be
describe as a custom entry point to the data service. Service operations
are compassable and they follow the URI schema of the data service.

Why to Use Service Operations?

Making all the data in a data service available to everybody, with full access, should
raise a big question mark for you as a developer (I hope). In many cases, applications
need to implement business rules such as validations or imposing access policies to
specific clients. We saw in my previous post how we can use the interception
mechanism to do some of these things. But sometimes the interception mechanism is
not enough to run custom logic on a data service. This is why service operations were
created.

How to Implement a Service Operation?

The following code shows how you implement a service operation in your data service:

    public class ServiceOperationsDataService : DataService<SchoolEntities>

    {

        // This method is called only once to initialize service-wide policies.

        public static void InitializeService(IDataServiceConfiguration config)

        {

            config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);

 

            // Service operations access configuration.

            config.SetServiceOperationAccessRule("CoursesByCredits",

                      ServiceOperationRights.All);

        }

 

        #region Service Operation

 

        [WebGet]

        public IQueryable<Course> CoursesByCredits(int credits)

        {

            return this.CurrentDataSource.Course.Where(

                "it.Credits = @credits",

                new ObjectParameter("credits", credits));

        }

 

        #endregion

    }

In the example, the service operation returns all the courses that their
credits is equal to the credits input parameter. You can see that you need
to configure the service operation access rules in the InitializeService method.

Service Operation Strict Implementation Rules

The following rules must be address when you create a service operation:

  • Service operation need to have a public modifier and should be inside
    of the data service.
  • Service operation need to have the [WebGet] attribute to enable invoking of
    HTTP GET requests or [WebInvoke] attribute to enable invoking of HTTP POST,
    PUT or DELETE requests.
  • Service operation need to return one of the following options - void,
    IEnumerable<T> or an IQueryable<T>. If you want to return a single entity
    rather than a collection of entities, you should add the SingleResult
    attribute to the service operation definition.

Invoking a Service Operation

In order to invoke a service operation you use the same URL approach like
the invoking of resources exposed by the data service. Calling
http://localhost:4528/ServiceOperationsDataService.svc/CoursesByCredits?credits=2
will invoke the service operation on the 2 parameter. As you can see from this
example the query string parameters are mapped directly to the method
arguments.

Summary

Lets sum up, ADO.NET Data Services enable definition of service operations to
extend the model of mapping URIs to resources. You should use this feature to
expose business logic from data services and to restrict the access to the data
service
resources. I think that using the service operations will help to remove the
concept of exposing all your database through a data service which is in my
opinion a design error (you want to expose data but not database!). 

Deep Code Analysis With NDepend

Deep Code Analysis With NDepend

A few weeks ago,NDepend
I was contacted by
Patrick Smacchia,
a C# MVP, that I 
read his articles on
one of my favorite
blog sites – CodeBetter.
Patrick asked me if I want to evaluate NDepend professional edition.
Without thinking twice, I agreed and this post is a review of the product.
I want to thank Patrick for the opportunity to evaluate a professional product
which I wanted to test for a while (I downloaded the evaluation edition a few
weeks before Patrick contact me and now I had the opportunity to download
the professional edition).

What is NDepend?

From NDepend site:
NDepend is a tool that simplifies managing a complex .NET code base. Architects and
developers can analyze code structure, specify design rules, plan massive refactoring,
do effective code reviews and master evolution by comparing different versions of the
code.

The result is better communication, improved quality, easier maintenance and
faster development.”

NDepend is a great tool!
It is a static analyzer for a compiled code. It is suited for developers and architects
that want to analyze the written code and get very helpful output data.
The output data that NDepend produces can help to improve the
code quality and design. At first, I thought That the tool resembles the FxCop tool
but as I tested it further, I now understand that it allows me to drill down better and
deeper into my code and also it supplies a visual analysis that is more intuitive for me.

NDepend Features

NDepend has the following features:

I can tell that the most awesome feature is the CQL (Code Query
Language) which enables to write SQL like queries to get reflection details.
In FxCop to do the same thing enforces you to write rules or plug-ins which are less
intuitive then the CQL.

Documentation, Documentation, Documentation

The most helpful thing about NDepend is its documentation. Sometimes, when I
download a tool or a product, I wish that it’ll be documented properly. Most of the
tools aren’t documented at all or have a minor documentation. This issue is very
annoying because you pay a lot of money for tools and you expect that it will have
a decent documentation. The NDepend site is full of documentation and screen
casts that help to get start with the tool very fast.

Some Small Examples

When NDepend load you get the following startup page:
NDepend Start Page

As you can see, the tool can be integrated into Visual Studio (2005, 2008)
and also into reflector (which is a must have tool for a developers).

I used the New Project button from the File menu to build a new analysis project:
NDepend New Project View

You can now Browse or Drag & Drop assemblies to be analyzed.

After I dragged a simple assembly I got the following results:
NDepend At Action 

What you can see in the screen are Dependency Graph, Dependency Matrix
and the Metrics View which is set to the number of code lines in my example.
In the bottom are the CQL Queries View which enables the use of CQL to
inspect the code. This is only a minor assembly and NDepend gave me a lot of details
that I used to refactor the assembly and now the code is better written.

Summary

NDepend is a highly professional product. With its variety of features it can
supply a very deep analysis to the code you write. I only scratched the surface of
the product in this review.
One last important thing, I wasn’t paid or obligated to write this review and its my thoughts
only. I think a tool like NDepend can really help you to get a deep insight and perspective
on how you build your application and then help you to improve your code.

Interceptions in ADO.NET Data Services

Interceptions in ADO.NET Data Services

In the following post ADO.NET Data Services Query Interception
I’m going to explain
the interception
mechanism of
ADO.NET data
services
.

Query Interception in Data Services

The ADO.NET data services comes with a plug in mechanism which
is called interception. That mechanism enables us to intercept a
data service’s incoming query or operation and to plug in custom validation,
access policy logic or whatever we like into the pipeline of that data service.
For example, if I’ll like to validate that a course has more then three days, I
can implement an interceptor that will do that filter.

How to Implement Query Interception?

Query interception is enabled through the QueryInterceptor attribute.
We decorate the intercepting method with that attribute.
The QueryInterceptor gets an entity set name as parameter. We need to
return the expression that will be performed on every entity in the entity
set. An example for a query interception method signature can look like:

[QueryInterceptor("Courses")]

public Expression<Func<Course, bool>> FilterCourses()

{

   // implement interception logic

}

If I’ll like to implement a filter that returns only courses with duration bigger
then three days the method can look like:

[QueryInterceptor("Courses")]

public Expression<Func<Course, bool>> FilterCourses()

{

   return (c => c.Days > 3);

}

How to Implement Modification Operation Interception?

Modification operation interception is enabled through ChangeInterceptor
attribute. We decorate the intercepting method with that attribute. As the
QueryInterceptor attribute, the ChangeInterceptor attribute gets as
parameter the entity set name as parameter. An example of method
signature of such a method can look like:

[ChangeInterceptor("Courses")]

public void OnChangeCourses(Course course, UpdateOperations operation)

{

   // implement interception logic

}

Unlike the query interception methods, the modification operation
interception
doesn’t return an expression. We need to have two incoming
parameters – the entity that the operation will perform on and the operation
type which is represented by the UpdateOperations enum.
Pay attention, to have the entity from the entity set you registered in the
ChangeInterceptor or else the interception won’t work.
The next example I’m throwing an exception if somebody tries to insert or
update a course to have more then five points credit:

[ChangeInterceptor("Courses")]

public void OnChangeCourses(Course course, UpdateOperations operation)

{

   switch (operation)

   {               

      case UpdateOperations.Change:

      case UpdateOperations.Add:

         {

            if (course.Credit > 5)

            {

               throw new DataServiceException(

                  "Can't have more then 5 points credit course");

            }

            break;

         }               

         default:

            {

               break;

            }

      }          

}

The Full Example Code

public class CoursesService : DataService<CoursesDataContext>

{

   // This method is called only once to initialize service-wide policies.

   public static void InitializeService(IDataServiceConfiguration config)

   {

      config.SetEntitySetAccessRule("*", EntitySetRights.All);

   }

 

   #region Interception Examples

 

   [QueryInterceptor("Courses")]

   public Expression<Func<Course, bool>> FilterCourses()

   {

      return (c => c.Days > 3);

   }

 

   [ChangeInterceptor("Courses")]

   public void OnChangeCourses(Course course, UpdateOperations operation)

   {

      switch (operation)

      {               

         case UpdateOperations.Change:

         case UpdateOperations.Add:

            {

               if (course.Credit > 5)

               {

                  throw new DataServiceException(

                     "Can't have more then 5 points credit course");

               }

               break;

            }               

         default:

         {

            break;

         }

      }          

   }

 

   #endregion

}

Summary

Lets sum up, in the post I showed how you can use the interception
mechanism that comes with the data services implementation. That
mechanism can help us to hook operations like validation or access policy
logic into the data services in a very simple manner.