Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / database / SQL-Server

GPS Tracer Extension: storing the path on SQL2005 via Web Services

4.53/5 (9 votes)
7 Sep 20075 min read 3   427  
This article extends Leonardo Salvatore's project "A GPS tracer application for Windows Mobile CE 5" using the Web Service Software Factory. It shows how to create a robust solution for storing the path on a DB server, using Web Services and SQL
Screenshot - Article.gif

Introduction

In this article we want to add a simple extension to the project seen in the CodeProject article "A GPS tracer application for Windows Mobile CE 5". We want to create a Web Service which can be invoked by the mobile application to store the path followed by different GPS devices on a remote SQL2005 Database. The easiest and fastest way to achieve this result is represented by the Web Service Software Factory (WSSF for short). At the same time, this strategy is the best way to build higher quality service using well known patterns and practices.

Background

A GPS tracer application for Windows Mobile CE 5; Web Services Software Factory

Using the code

Our goal is incredibly simple: we just want to store an ordered collection of GPS coordinates (a path) sent by a mobile device. Obviously we desire to distinguish between different devices, and respective paths, which can send information contemporarily.

First of all, I created two tables in a database named GpsTracer: the tables are Device and LocationEntry and are defined by the following SQL statements:

SQL
CREATE TABLE [dbo].[Device](
    [ID] [uniqueidentifier] NOT NULL CONSTRAINT [DF_Device_ID] _ 
                        DEFAULT (newid()),
    [CreationDate] [datetime] NOT NULL,
    [LastLoginDate] [datetime] NOT NULL,
 CONSTRAINT [PK_Device] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

GO

CREATE TABLE [dbo].[LocationEntry](
    [ID] [uniqueidentifier] NOT NULL CONSTRAINT [DF_LocationEntry_ID] _  
                            DEFAULT (newid()),
    [IDDevice] [uniqueidentifier] NOT NULL,
    [Latitude] [float] NULL,
    [Longitude] [float] NULL,
    [WhenInserted] [datetime] NULL,
    [Speed] [float] NULL,
    [Quote] [float] NULL,
    [Heading] [float] NULL,
 CONSTRAINT [PK_LocationEntry] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]GO
ALTER TABLE [dbo].[LocationEntry]  WITH CHECK ADD  CONSTRAINT _
            [FK_LocationEntry_Device] FOREIGN KEY([IDDevice])

This structure is quite simple but it's powerful enough for our purpose; we just want to collect the devices connected (identified by their Guid) and their first and last connection to the system (device table); we want to know the paths they have ever followed (LocationEntry table). Please note that the structure and tables of the database are the foundation of the solution built with the WSSF (and not only with that!) so we suggest thinking about them carefully before starting with the code generation. Of course, due to the nature of this "demo-project", we can go on.

After the database definition, the biggest part of the rough work is done by the WSSF. Once we create a new project of type "Web Service Software Factory (ASMX)" in Visual Studio, we should follow these steps (please refer to the Visual Studio Guidance Navigator window and it's "recipes" for more details; please remember to rebuild the solution between the steps):

  • Connect the infrastructure to the database in the Service project: a connection string is added to the web.config file
  • Create The CRUD Stored Procedure for the database tables in the Data Access Project: an SQL statement file is generated (see GpsTracerStoredCreation.sql)
  • Create the Business Entities based on the database tables in the Business Entity project: the classes Device and LocationEntry are created
  • Create the Data Repository Classes from Business Entities in the Data Access Project: the classes for connecting the entities and the database are created
  • Create a Data Type accepted by the Web Service: the objects of this type will be the ones sent by the mobile application to the web server and they will contain all the information needed for the insertion of a "footstep" (a single step in the GPS path) in the database. In our case the type "DeviceAndLocation" contains the fields of both the database tables: deviceID, deviceCreationDate, deviceLastLoginDate, locationEntryLatitude, locationEntryLongitude and so on
  • Create a Service Contract in the corresponding project: this is the signature of the Web Method that will be created. In our example it is named SendDeviceAndLocation, it returns a Boolean and has one input parameter of type DeviceAndLocation
  • Create the Service Contract Translators from the data type to the Business Entities. In our example this direction is enough because our application just receives data from the mobile devices. We define two translators: one from the data type to the device BE and one from the data type to the location BE
  • Add business logic to our solution: in our simple solution we add the class DeviceAndLocationBLL with the single method AcquireDeviceAndLocation (see code described below)
  • Generate the Service Implementation: here we can finally implement our service (see code described below)
  • Expose the service: the asmx file is generated
  • Add web reference and implement a test in the windows form test project to check if insertion goes well!

Points of Interest

The few lines of code that we have to write are related to the method in the business logic and the service method. Let's start with the BLL.

This method checks if the device that sends information is already in the Device table: if it is present then we update its last login date, else we insert it into the table.

It's peculiarity consists in the use of the GetAllFromDevice (automatically created as Data Repository Classes from the CRUD stored procedures) the result of which is filtered with the find method of a "generics list". The Predicate of the find method is an anonymous delegate that checks if the ID of the input device parameter "fits" into an element of the list. Please note that the method is STATIC: a class method is preferable for the performances and we should not mind atomicity of operations due to the use of the database.

C#
public class DeviceLocationBll
{
    public static bool AcquireDevice(Device inDev, LocationEntry inLoc)
    {
        DeviceRepository devRep = new DeviceRepository("GpsTracer"); 
        //"GpsTracer" is the name of the connection string in web.config

        List<device /> listDev = devRep.GetAllFromDevice();

        Device devResult = listDev.Find(
            new Predicate<device />(
                delegate(Device devv)
                {
                    return devv.ID == inDev.ID;
                }
            )
        );
        if (devResult == null)
        {
            devRep.Add(inDev);
        }
    Else
    {
        devResult.LastLoginDate = DateTime.Now();
    }

        LocationEntryRepository locRep = new LocationEntryRepository
                                ("GpsTracer");
        locRep.Add(inLoc);
            
        return true;
    }
}

The service implementation is quite easy: we just need to translate the object received from the web and pass the results to the AcquireDevice method.

C#
public bool SendDeviceAndLocationInfos
        (GpsTracerServer.DataTypes.DevicePlusLocationType 
                    SendDeviceAndLocationInfosRequest)
    {
        BusinessEntities.Device dev = 
        TranslateBetweenDevicePlusLocationTypeAndDevice.
        TranslateDevicePlusLocationTypeToDevice
        (SendDeviceAndLocationInfosRequest);
        BusinessEntities.LocationEntry loc = 
        TranslateBetweenDevicePlusLocationTypeAndLocationEntry.
        TranslateDevicePlusLocationTypeToLocationEntry
        (SendDeviceAndLocationInfosRequest);

        return DeviceLocationBll.AcquireDevice(dev,loc);
    }

A very simple test implementation in the windows form is the following: we instantiate the proxy class which is needed to translate our DeviceAndLocation to the corresponding soap packet.

C#
private void ExecuteButton_Click(object sender, EventArgs e)
{
    //TODO: Call proxy method
    GpsTracerServiceContract ws = new GpsTracerServiceContract();

    DeviceAndLocation testDev = new DeviceAndLocation ();
    testDev.DeviceID = new Guid().ToString();
    testDev.DeviceCreationDate = DateTime.Now;
    testDev.DeviceLastLoginDate = DateTime.Now;
    testDev.LocationHeading = 10;
    testDev.LocationLatitude = 11;
    testDev.LocationLongitude = 12;
    testDev.LocationQuote = 13;
    testDev.LocationSpeed = 14;
    testDev.LocationWhenInserted = DateTime.Now;

    ws.SendDeviceAndLocationInfos(testDev);
}

In this article, we used the Web Service Software Factory and the result is a simple web service based on a robust, extensible, well engineered foundation. We just emphasize that the entire solution can be built in 15 minutes and with a few lines of code.

History

Nothing to add... at this moment!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here