65.9K
CodeProject 正在变化。 阅读更多。
Home

GPS Tracer 扩展: 通过 Web 服务将路径存储在 SQL2005 上

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.72/5 (7投票s)

2007 年 8 月 22 日

5分钟阅读

viewsIcon

29637

downloadIcon

301

本文扩展了 Leonardo Salvatore 的项目, 使用 Web Service Software Factory

Screenshot - Article.gif

引言

在本文中,我们想为 CodeProject 文章 A GPS Tracer Application for Windows Mobile CE 5 中看到的项目添加一个简单的扩展。我们想创建一个 Web 服务,移动应用程序可以调用该服务,将不同 GPS 设备跟踪的路径存储在远程 SQL2005 数据库中。实现此结果最简单快捷的方法是使用 Web Service Software Factory(简称 WSSF)。这种策略同时也是使用众所周知的模式和实践来构建更高质量服务的最佳方式。

背景

一款适用于 Windows Mobile CE 5 的 GPS 跟踪器应用程序;Web Services Software Factory

Using the Code

我们的目标非常简单:我们只想存储由移动设备发送的 GPS 坐标的有序集合(一条路径)。显然,我们希望区分同时发送信息的不同设备及其各自的路径。

首先,我在一个名为 GpsTracer 的数据库中创建了两个表:DeviceLocationEntry,它们由以下 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])

此结构非常简单,但足以满足我们的目的:我们只想收集已连接的设备(由其 Guid 标识)以及它们与系统的首次和最后一次连接(设备表);我们想知道它们曾经走过的路径(LocationEntry 表)。请注意,数据库的结构和表是使用 WSSF(以及不限于此!)构建的解决方案的基础,因此我们建议在开始代码生成之前仔细考虑它们;当然,由于这是一个“演示项目”,我们可以继续进行。

在数据库定义之后,WSSF 完成了大部分粗糙的工作。一旦我们在 Visual Studio 中创建了一个类型为“Web Service Software Factory (ASMX)”的新项目,我们应该遵循以下步骤(有关更多详细信息,请参阅 Visual Studio Guidance Navigator 窗口及其“配方”;请记住在步骤之间重建解决方案)

  • 将基础结构连接到服务项目中的数据库:连接字符串已添加到 web.config 文件中
  • 在数据访问项目中为数据库表创建 CRUD 存储过程:生成一个 SQL 语句文件(请参阅 GpsTracerStoredCreation.sql
  • 在业务实体项目中基于数据库表创建业务实体:创建 Device LocationEntry
  • 在数据访问项目中从业务实体创建数据存储库类:创建用于连接实体和数据库的类。
  • 创建一个 Web 服务可接受的数据类型:此类型对象将是移动应用程序发送到 Web 服务器的对象,它们将包含将“足迹”(GPS 路径中的单步)插入数据库所需的所有信息。在我们的例子中,类型 DeviceAndLocation 包含两个数据库表的字段:deviceIDdeviceCreationDatedeviceLastLoginDatelocationEntryLatitudelocationEntryLongitude 等。
  • 在相应的项目中创建一个服务契约:这是将创建的 Web 方法的签名。在我们的示例中,它被命名为 SendDeviceAndLocation,它返回一个 Boolean,并有一个类型为 DeviceAndLocation 的输入参数。
  • 从数据类型到业务实体的服务契约转换器。在我们的例子中,这个方向已经足够了,因为我们的应用程序只接收来自移动设备的数据。我们定义了两个转换器:一个从数据类型到设备 BE,另一个从数据类型到位置 BE。
  • 向我们的解决方案添加业务逻辑:在我们简单的解决方案中,我们添加了 DeviceAndLocationBLL 类,其中包含单个方法 AcquireDeviceAndLocation (请参阅下面的代码)。
  • 生成服务实现:在这里,我们可以最终实现我们的服务(请参阅下面的代码)。
  • 公开服务:ASMX 文件已生成。
  • 在 Windows 窗体测试项目中添加 Web 引用并实现一个测试,以检查插入是否成功!

关注点

我们需要编写的几行代码与业务逻辑中的方法和方法相关。让我们从 BLL 开始。

此方法检查发送信息的设备是否已存在于 Device 表中:如果存在,则更新其最后登录日期,否则将其插入表中。

其独特性在于使用了 GetAllFromDevice (从 CRUD 存储过程自动创建的数据存储库类),其结果通过“泛型列表”的 find 方法进行过滤。find 方法的谓词是一个匿名委托,它检查输入设备参数的 ID 是否“适合”列表中的某个元素。请注意,该方法是 STATIC 的:类方法出于性能考虑是首选,由于使用了数据库,我们无需担心操作的原子性。

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;
    }
}

服务实现非常简单:我们只需要转换从 Web 收到的对象,并将结果传递给 AcquireDevice 方法。

public bool SendDeviceAndLocationInfos
    (GpsTracerServer.DataTypes.DevicePlusLocationType 
        SendDeviceAndLocationInfosRequest)
        {
            BusinessEntities.Device dev =
    TranslateBetweenDevicePlusLocationTypeAndDevice.
     TranslateDevicePlusLocationTypeToDevice
        (SendDeviceAndLocationInfosRequest);
            BusinessEntities.LocationEntry loc = 
    TranslateBetweenDevicePlusLocationTypeAndLocationEntry.
     TranslateDevicePlusLocationTypeToLocationEntry
        (SendDeviceAndLocationInfosRequest);
            return DeviceLocationBll.AcquireDevice(dev,loc);
        }

Windows 窗体中的一个非常简单的测试实现如下:我们实例化了代理类,该类需要将我们的 DeviceAndLocation 转换为相应的 soap 数据包。

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);
}

在本文中,我们动手实践了 Web Service Software Factory,最终得到了一个基于健壮、可扩展、精心设计的底层基础的简单 Web 服务。我们只是强调,整个解决方案可以在 15 分钟内完成,并且只需要几行代码。

历史

目前!

© . All rights reserved.