tslintのインストール

こんにちは。beaglesoftの真鍋です。

最近はRailsとTypeScriptでの開発が中心になってきました。TypeScriptはJavaScriptを書いていることを忘れさせてくれるのですが、そうはいってもきちんとやることをやる必要があるなと思うことがありましたので、規約をチェックするためにTslintをインストールすることにしました。

TSLint

なお、以下の手順はあらかじめTypeScriptで開発できる環境が整っていることを前提とします。

インストール

tslintのインストールはnpmで行います。すべてのプロジェクトで利用するのでシステムグローバルにインストールします。

$ sudo npm install -g tslint typescript
[sudo] password for ymanabe: 
/usr/local/bin/tslint -> /usr/local/lib/node_modules/tslint/bin/tslint
/usr/local/bin/tsc -> /usr/local/lib/node_modules/typescript/bin/tsc
/usr/local/bin/tsserver -> /usr/local/lib/node_modules/typescript/bin/tsserver
/usr/local/lib
├─┬ tslint@3.13.0 
│ ├── colors@1.1.2 
│ ├── diff@2.2.3 
│ ├─┬ findup-sync@0.3.0 
│ │ └── glob@5.0.15 
│ ├─┬ glob@7.0.5 
│ │ ├── fs.realpath@1.0.0 
│ │ ├─┬ inflight@1.0.5 
│ │ │ └── wrappy@1.0.2 
│ │ ├── inherits@2.0.1 
│ │ ├─┬ minimatch@3.0.2 
│ │ │ └─┬ brace-expansion@1.1.6 
│ │ │   ├── balanced-match@0.4.2 
│ │ │   └── concat-map@0.0.1 
│ │ ├── once@1.3.3 
│ │ └── path-is-absolute@1.0.0 
│ ├─┬ optimist@0.6.1 
│ │ ├── minimist@0.0.10 
│ │ └── wordwrap@0.0.3 
│ ├── resolve@1.1.7 
│ └─┬ underscore.string@3.3.4 
│   ├── sprintf-js@1.0.3 
│   └── util-deprecate@1.0.2 
└── typescript@1.8.10 

tslint.jsonの生成

インストールが完了したら、設定ファイルを作成します。

$ cd /path/to/project
$ tslint -i 

これで /path/to/project にtslint.jsonが作成されます。今回はTypeScriptで今すぐ使える実践的『ECMAScript 2015』 | HTML5Experts.jpを参考にして"use-strict"のチェックを行いたいと思ったのでデフォルトのtslint.jsonに追加しました。

use-strictを導入したtslint.config

実行する

設定ファイルの作成が完了したら実際に実行してみます。何も引っかからなければ特に何も表示されません。

$ tslint -c ./tslint.json app/assets/javascripts/common/dhtmlxHelper.ts
app/assets/javascripts/common/dhtmlxHelper.ts[7, 1]: missing 'use strict'

lintでチェックした内容は以下の通りです。

/// <reference path="../../../../typings/index.d.ts" />

declare var dhtmlXCalendarObject: any;

export namespace common.dhtmlx {

// ↓ここをコメントアウトした
// "use strict";

    /**
     * このモジュールはDHTMLXライブラリのサポート用クラス
     */
    export class DhtmlxHelper {
...
    }
}

確かに"use strict"が設定されていない場合にはエラーが表示されます。

RubyMineでの設定

今回はIDEとしてRubyMineを利用しているので、その設定もあわせて確認します。

メニューの File -> Settings から Settingsを表示して、Languages & Frameworks > TypeScript > TSLint を表示します。

表示した画面のEnableチェックボックスにチェックし、TSLint package のドロップダウンをクリックして表示される内容を選択します。また、Configuration fileでは Search fo tslint.json を選択します。

rubymine_tslint.jpg (112.5 kB)

これで対象のファイルを開くとこの通りエラーが表示されます。

rubymine_tslint2.jpg (14.5 kB)

あとは、CIの中でチェックをするなどすれば良いのではと思います。その辺はもう少し後で試そうと思います。

C#でDbGeographyに定義したPolygonの巻きを補正する

こんにちは。beaglesoftの真鍋です。

SQL ServerでGeographyのポリゴンを扱う場合には右巻/左巻で世界が一変するわけで、結構重要です。普通はSQL Serverで以下のクエリを発行すればよしなに行ってくれます。

-- geomがポリゴンを保存しているGeeography型の列

-- 巻きが逆の場合に補正します
update `テーブル名` set [geom] = [geom].MakeValid().ReorientObject() where [geom].MakeValid().EnvelopeAngle() > 90

-- 有効なインスタンスに補正します
update `テーブル名` set [geom] = [geom].MakeValid() where [geom].STIsValid() = 0

ただ、EntityFrameworkを使っているとこの処理だけSQLを実行するのも手間です。そこで、DbGeography型で対応できないかと調べたのですが、現在のところDbGeometory型に変換してからでないと処理ができないことがわかりました。

うーんと思っていたところ、どうやら以下の方法で同じことができることがわかりました。

/// <summary>
/// 経度 緯度,経度 緯度...の文字列からポリゴンを生成します。
/// </summary>
/// <param name="polygonText">経度 緯度,経度 緯度...の文字列</param>
/// <returns>DbGeoGraphyのインスタンス</returns>
public static DbGeography ConvertToPolygon(string polygonText)
{
    if (string.IsNullOrEmpty(polygonText))
    {
        throw new ArgumentNullException();
    }

    var sqlGeography = SqlGeography.STGeomFromText(new SqlChars($"POLYGON(({polygonText}))"), 4326).MakeValid();
    if (sqlGeography.EnvelopeAngle() > 90)
    {
        sqlGeography = sqlGeography.ReorientObject();
    }

    return DbSpatialServices.Default.GeographyFromProviderValue(sqlGeography);
}

行っていることはSQLと同じですので省略しますが、これは便利です。SqlGeographyはMicrosoft.SqlServer.Types 名前空間に定義されているクラスで、DbGeographyよりも多くの処理が定義されているようです。もともとWKTを介してデータの変換は DbGeometory⇔DbGeography と行えるのですが、こっちはより便利ですね。

参考にしたサイト

How to correct Polygon Ring Orientation using C# Entity Framework 5 DbGeography Spatial Data - Stack Overflow

DbGeography Reverse Polygon Point Order (Ring Orientation) With Entity Framework 5, WKTString and MSSQL 2008 | Tales of a White Robe

SqlServerSpatial110.dllが見つかりません

こんにちは。beaglesoftの真鍋です。

SQL ServerからGeography型のデータを取得するときに、「SqlServerSpatial110.dllが見つかりません」というエラーが出ることがあります。最初は何のことかさっぱりわからなかったのですが、いろいろと調べたところDbGeoGraphy型が内部でSqlServerSpatial110.dllを利用しているため、あらかじめプログラムの実行時にはロードしておく必要が有るけれども、そのロードを行っていないと発生するエラーのようです。

対応方法としては次の通り対応することで利用可能になりました。

  1. NuGet Packageをインストールする。
  2. アプリケーションごとにロード方法を設定する。
  3. App.configまたはweb.configにバージョンを追加する。

NuGet Packageをインストールする

NuGet Packageのインストールは以下のとおり実行可能です。

Install-Package Microsoft.SqlServer.Types

NuGet Gallery | Microsoft.SqlServer.Types (Spatial) 11.0.2

アプリケーションごとにロード方法を設定する

NuGetのインストール時に表示されるReadmeに記述が表示されますが、以下の設定を行う必要があります。

ASP.NETアプリケーション

Global.asaxApplication_Startメソッドで以下の設定を記述する必要があります。

SqlServerTypes.Utilities.LoadNativeAssemblies(Server.MapPath("~/bin"));

Windowsアプリケーション

Windowsアプリケーションではアプリケーションの起動時に以下の設定を記述する必要があります。(厳密には、SqlServerSpatial110.dllが実行される前までに読み込まれていれば良いと記述があります。)

SqlServerTypes.Utilities.LoadNativeAssemblies(AppDomain.CurrentDomain.BaseDirectory);

ユニットテスト

ユニットでストでは、ユニットテストクラスにも上記のNuGet Packageをインストールする必要があります。また、SqlServerSpatial110.dllを利用した処理を実行するテストクラスでは以下のとおり予め読み込み処理を実行する必要があります。

[ClassInitialize]
public static void ClassInitialize(TestContext context)
{
    SqlServerTypes.Utilities.LoadNativeAssemblies(AppDomain.CurrentDomain.BaseDirectory);
}

App.configまたはweb.configにバージョンを追加する

App.configまたはweb.configに以下の通りバージョンを指定します。

<runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.SqlServer.Types" publicKeyToken="89845dcd8080cc91" culture="neutral" />
        <bindingRedirect oldVersion="10.0.0.0" newVersion="11.0.0.0" />
      </dependentAssembly>
     ...

参考にしたサイト

.net - SqlServerSpatial110.dll failed to copy on Windows Azure deployment - Stack Overflow .net - SqlServerSpatial110.dll failed to copy on Windows Azure deployment - Stack Overflow Microsoft.SqlServer.Types NuGet Package (Spatial on Azure) - ADO.NET Blog - Site Home - MSDN Blogs