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

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.53/5 (9投票s)

2007 年 9 月 7 日

5分钟阅读

viewsIcon

34532

downloadIcon

442

本文扩展了 Leonardo Salvatore 的项目“Windows Mobile CE 5 的 GPS 追踪器应用程序”,使用了 Web Service Software Factory。本文展示了如何使用 Web Services 和 SQL 创建一个健壮的解决方案,用于将路径存储在数据库服务器上。

Screenshot - Article.gif

引言

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

背景

Windows Mobile CE 5 的 GPS 追踪器应用程序;Web Services Software Factory

使用代码

我们的目标非常简单:我们只想存储由移动设备发送的 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 标识)以及它们与系统的第一次和最后一次连接(device 表);我们想知道它们曾经走过的路径(LocationEntry 表)。请注意,数据库的结构和表是使用 WSSF(以及不仅仅是 WSSF!)构建的解决方案的基础,因此我们建议在开始代码生成之前仔细考虑它们。当然,由于这是一个“演示项目”的性质,我们可以继续进行。

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

  • 将基础设施连接到 Service 项目中的数据库:在 web.config 文件中添加了连接字符串。
  • 在 Data Access Project 中为数据库表创建 CRUD 存储过程:生成了一个 SQL 语句文件(参见 GpsTracerStoredCreation.sql)。
  • 在 Business Entity 项目中根据数据库表创建 Business Entities:创建了 DeviceLocationEntry 类。
  • 在 Data Access Project 中从 Business Entities 创建 Data Repository Classes:创建了用于将实体和数据库连接起来的类。
  • 创建一个 Web Service 可以接受的数据类型:此类型对象将是移动应用程序发送到 Web 服务器的对象,它们将包含插入数据库中的“足迹”(GPS 路径中的单步)所需的所有信息。在我们的例子中,“DeviceAndLocation”类型包含两个数据库表的字段:deviceIDdeviceCreationDatedeviceLastLoginDatelocationEntryLatitudelocationEntryLongitude 等。
  • 在相应的项目中创建一个 Service Contract:这是将要创建的 Web Method 的签名。在我们的示例中,它名为 SendDeviceAndLocation,它返回一个布尔值,并有一个类型为 DeviceAndLocation 的输入参数。
  • 从数据类型到 Business Entities 创建 Service Contract Translators。在我们的例子中,这个方向就足够了,因为我们的应用程序只接收来自移动设备的数据。我们定义了两个转换器:一个从数据类型到设备 BE,一个从数据类型到位置 BE。
  • 向我们的解决方案添加业务逻辑:在我们简单的解决方案中,我们添加了 DeviceAndLocationBLL 类,其中包含单个方法 AcquireDeviceAndLocation(请参见下面的代码描述)。
  • 生成 Service Implementation:在这里,我们终于可以实现我们的服务了(请参见下面的代码描述)。
  • 公开服务:生成了 asmx 文件。
  • 添加 Web 引用并在 Windows 窗体测试项目中实现测试,以检查插入是否顺利!

关注点

我们必须编写的几行代码与业务逻辑中的方法和 Service 方法有关。让我们从 BLL 开始。

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

其独特性在于使用了 GetAllFromDevice(由 CRUD 存储过程自动创建为 Data Repository Classes),其结果使用“泛型列表”的 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;
    }
}

Service 实现非常简单:我们只需要转换从 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 Service,它基于一个健壮、可扩展、设计精良的基础。我们只是强调,整个解决方案可以在 15 分钟内用几行代码完成。

历史

此时,没有什么可以补充的了!

© . All rights reserved.