ゆるふわエンジニアのブログ

やったこと、調べたこと等をつらつらと書いていくかもしれません。

PetaPocoを触ってみた(導入、簡単な操作編)(Micro-ORM)

Micro-ORMのPetaPocoを触ってみたので、記事として残しておきます。
サンプルコードはすべてC#で書いています。

お品書き

PetaPocoについて

PetaPoco - Topten Software

インストール

以下のコマンドをパッケージマネージャコンソールで実行するだけです。

Install-Package PetaPoco -Version 5.1.244

バージョンを指定しないと古いバージョンのものが
インストールされてしまいますので、注意してください。
最新バージョンは以下URL先で確認することができます。
www.nuget.org

簡単な操作方法

コネクション作って、App.configの情報を元に接続して、
トランザクション開始して、各操作を行い、
最後に接続を切断しています。
Insert、Update、Deleteは、上記以外にコミット、ロールバックを行っていますね。
例外が発生しなければコミット、
例外が発生したらロールバックという実装にしています。

使用しているEntityクラス

クラス名はテーブル名と同じ、プロパティ名は列名と同じにしてあります。

class USER_MASTER
{
    public string USER_ID { get; set; }
    public string DEPT_NO { get; set; }
    public string USER_NAME { get; set; }
    public DateTime? CREATED_ON { get; set; }
    public DateTime? MODIFIED_ON { get; set; }
}

Select

// 接続情報作成、接続
using(var db = new Database(connectionName))
{
    try
    {
        // トランザクション開始
        db.BeginTransaction();
        
        // Select
        var sql = @"SELECT * FROM USER_MASTER";
        var rows = db.Query<USER_MASTER>(sql);
        // Select(単一レコード)
        var sqlSingleRecord = @"SELECT * FROM USER_MASTER WHERE USER_ID = @USER_ID";
        var row = db.Query<USER_MASTER>(sqlSingleRecord, new { USER_ID = "0001" });
        // Select(特定列)
        var sqlFirstColumn = @"SELECT COUNT(1) FROM USER_MASTER";
        var count = db.ExecuteScalar<int>(sqlFirstColumn);
    }
    finally
    {
        // トランザクション終了(コミット)
        db.CompleteTransaction();
    }
}

Insert

// 接続情報作成、接続
using (var db = new Database(connectionName))
{
    try
    {
        // トランザクション開始
        db.BeginTransaction();

        // SQL文無しでInsert
        // テーブル名
        var tableName = "USER_MASTER";
        // Insert用インスタンス作成
        var insertObjNonSQL = new USER_MASTER() { USER_ID = "9999", DEPT_NO = "9999" };
        // Insert実行
        db.Insert(tableName, insertObjNonSQL);

        // SQL文有りでInsert
        // SQL文作成
        var sql = @"INSERT INTO USER_MASTER ( USER_ID, DEPT_NO ) VALUES ( @USER_ID, @DEPT_NO)";
        // Insert用インスタンス作成
        var insertObjSQL = new USER_MASTER() { USER_ID = "8888", DEPT_NO = "8888" };
        // Insert実行
        db.Execute(sql, insertObjSQL);

        // コミット
        db.CompleteTransaction();
    }
    catch
    {
        // ロールバック
        db.AbortTransaction();
        throw;
    }
}

Update

コネクションやトランザクション関係の処理はInsertと同じなため、省略しています。

// コネクションやトランザクション関係の前処理(省略)
// SQL文無しでUpdate
// テーブル名
var tableName = "USER_MASTER";
// Update用インスタンス作成
var updateObjNonSQL = new USER_MASTER() { USER_ID = "9999", USER_NAME = "HOGE" };
// Update実行
db.Update(tableName, nameof(updateObjNonSQL.USER_ID), updateObjNonSQL);

// SQL文有りでUpdate
// SQL文作成
var sql = @"UPDATE USER_MASTER SET USER_NAME = @USER_NAME WHERE USER_ID = @USER_ID";
// Update用インスタンス作成
var updateObjSQL = new USER_MASTER() { USER_ID = "8888", USER_NAME = "FUGA" };
db.Execute(sql, updateObjSQL);
// コネクションやトランザクション関係の後処理(省略)

Delete

// コネクションやトランザクション関係の前処理(省略)
// SQL文無しでDelete
// テーブル名
var tableName = "USER_MASTER";
// Delete用インスタンス作成
var deleteObjNonSQL = new USER_MASTER() { USER_ID = "9999" };
// Delete実行
db.Delete(tableName, nameof(deleteObjNonSQL.USER_ID), deleteObjNonSQL);

// SQL文有りでDelete
// SQL文作成
var sql = @"DELETE FROM USER_MASTER WHERE USER_ID = @USER_ID";
// DElete用インスタンス作成
var deleteObjSQL = new USER_MASTER() { USER_ID = "8888" };
// Delete実行
db.Execute(sql, deleteObjSQL);
// コネクションやトランザクション関係の後処理(省略)


いろいろと隠蔽されており、若干コードがスッキリしますね。
Attriubteを使っていないのでアレコレ書いていますが、
Attirbuteを使うとSQL文無しでのInsert、Update、Delete時に
テーブル名や主キー列を指定してやらなくてもよくなるので、
かなり楽にかつ短くコーディングできそうです。

あと、バインド変数の記号がすべて"@"っぽいんですけども、
もしかしてDBの種類に関係なく"@"...?

DeclarativeSqlを触ってみた(導入、簡単な操作編)(ORM)

簡単にDBを操作できるライブラリを探している中で、
DapperをベースにしたDeclarativeSqlというライブラリを見つけ
触ってみたので、記事として残しておきます。
Dapperの時と同じく、サンプルコードはC#で書いています。

お品書き

DeclarativeSqlとは

以下URLでどうぞ。
GitHub - xin9le/DeclarativeSql: Attribute-based database access
blog.xin9le.net

更新情報はこちらからも。
blog.xin9le.net
DeclarativeSql v0.2.2 リリース - xin9le.net

インストール

以下のコマンドをパッケージマネージャコンソールでそれぞれ実行するだけです。

Install-Package DeclarativeSql.Core
Install-Package DeclarativeSql.Dapper

簡単な操作方法

Dapperの時と同じです。
コネクション作って、App.configの情報を元に接続して、
トランザクション開始して、各操作を行い、
最後に接続を切断しています。
Insert、Update、Deleteは、上記以外にコミット、ロールバックを行っていますね。
例外が発生しなければコミット、
例外が発生したらロールバックという実装にしています。

使用しているEntityクラス

Dapper記事の時と同じく、クラス名はテーブル名と同じ、
プロパティ名は列名と同じにしてあります。

class USER_MASTER
{
    public string USER_ID { get; set; }
    public string DEPT_NO { get; set; }
    public string USER_NAME { get; set; }
    public DateTime? CREATED_ON { get; set; }
    public DateTime? MODIFIED_ON { get; set; }
}

Select

// 接続情報作成
using(var connection = DbProvider.CreateConnection(DbKind.Oracle, ConfigurationManager.ConnectionStrings[connectionName].ConnectionString))
{
    try
    {
        // 接続開始
        connection.Open();
        // トランザクション開始
        using (var transaction = connection.BeginTransaction())
        {
            // SQL文無しでSelect
            var rowsNonSQL = transaction.Select<USER_MASTER>(col => col.USER_ID == "0001");
            // SQL文有りでSelect
            var sql = @"SELECT * FROM USER_MASTER WHERE USER_ID = :USER_ID";
            var bindObj = new USER_MASTER() { USER_ID = "0001" };
            var rowsSQL = transaction.Query<USER_MASTER>(sql, bindObj);
        }
    }
    finally
    {
        // 接続切断
        connection.Close();
    }
}

Insert

// 接続情報作成
using (var connection = DbProvider.CreateConnection(DbKind.Oracle, ConfigurationManager.ConnectionStrings[connectionName].ConnectionString))
{
    try
    {
        // 接続開始
        connection.Open();
        // トランザクション開始
        using (var transaction = connection.BeginTransaction())
        {
            try
            {
                // SQL文無しでInsert
                // Insert用インスタンス作成
                var insertObjNonSQL = new USER_MASTER() { USER_ID = "9999", DEPT_NO = "9999" };
                // Insert
                var resultNonSQL = transaction.Insert(insertObjNonSQL);

                // SQL文でInsert
                // SQL文作成
                var sql = @"INSERT INTO USER_MASTER ( USER_ID, DEPT_NO ) VALUES ( :USER_ID, :DEPT_NO )";
                // Insert用インスタンス作成
                var insertObjSQL = new USER_MASTER() { USER_ID = "8888", DEPT_NO = "8888" };
                // Insert実行
                var resultSQL = transaction.Execute(sql, insertObjSQL);

                // コミット
                transaction.Commit();
            }
            catch
            {
                // ロールバック
                transaction.Rollback();
                throw;
            }
        }
    }
    finally
    {
        // 接続切断
        connection.Close();
    }
}

Update

// コネクションやトランザクション関係の前処理(省略)
// SQL文無しでUpdate
// Update用インスタンス作成
var updateObjNonSQL = new USER_MASTER() { USER_ID = "9999", USER_NAME = "HOGE" };
// Update
var resultNonSQL = transaction.Update(updateObjNonSQL, col => col.USER_ID == updateObjNonSQL.USER_ID);

// SQL文でUpdate
// SQL文作成
var sql = @"UPDATE USER_MASTER SET USER_NAME = :USER_NAME WHERE USER_ID = :USER_ID";
// Update用インスタンス作成
var updateObjSQL = new USER_MASTER() { USER_ID = "8888", USER_NAME = "FUGA" };
// Update実行
var resultSQL = transaction.Execute(sql, updateObjSQL);
// コネクションやトランザクション関係の後処理(省略)

Delete

// コネクションやトランザクション関係の前処理(省略)
// SQL文無しでDelete
// Delete
var resultNonSQL = transaction.Delete<USER_MASTER>(col => col.USER_ID == "9999");

// SQL文でDelete
// SQL文作成
var sql = @"DELETE FROM USER_MASTER WHERE USER_ID = :USER_ID";
// Delete用インスタンス作成
var DeleteObjSQL = new USER_MASTER() { USER_ID = "8888" };
// Delete実行
var resultSQL = transaction.Execute(sql, DeleteObjSQL);
// コネクションやトランザクション関係の後処理(省略)


DeclarativeSqlもDapperと同じくコネクション作成やらトランザクション開始やらの
お決まりのコードをどうにかしてやりたい感じですね。
でも、コネクション作成の作業が簡略化されていたり、
簡単な操作ならSQL文を書かなくても良かったり、利便性は確実に上がっています!
これは業務でも使いたいですね。
(今はすべてSQLを書いている。)

Dapperを触ってみた(導入、簡単な操作編)(Micro-ORM)

簡単にDBを操作できるライブラリを探している中で、
Dapperを見つけ触ってみたので、記事として残しておきます。

用途としては、EntityFrameworkと併用することが多いみたいですね。
EntityFrameworkでいけるところはEntityFrameworkを使用し、
手の届かない痒いところはDapperで対応する。といった感じでしょうか。
あ、サンプルの言語はC#です。

お品書き

Dapperとは

以下URLに載っていることを読んでください。(丸投げ)
GitHub - StackExchange/Dapper: Dapper - a simple object mapper for .Net

インストール方法

以下のコマンドをパッケージマネージャコンソールで実行するだけです。
簡単!

Install-Package Dapper

簡単な操作方法

コネクション作って、App.configの情報を元に接続して、
トランザクション開始して、各操作を行い、
最後に接続を切断しています。
Insert、Update、Deleteは、上記以外にコミット、ロールバックを行っていますね。
例外が発生しなければコミット、
例外が発生したらロールバックという実装にしています。

使用しているEntityクラス

クラス名はテーブル名と同じ、
プロパティ名は列名と同じにしてあります。

class USER_MASTER
{
    public string USER_ID { get; set; }
    public string DEPT_NO { get; set; }
    public string USER_NAME { get; set; }
    public DateTime? CREATED_ON { get; set; }
    public DateTime? MODIFIED_ON { get; set; }

    // プロパティの値確認用
    public override string ToString()
    {
        var retStr = new StringBuilder();
        retStr.AppendFormat("USER_ID:{0}\t", this.USER_ID);
        retStr.AppendFormat("DEPT_NO:{0}\t", this.DEPT_NO);
        retStr.AppendFormat("USER_NAME:{0}\t", this.USER_NAME);
        retStr.AppendFormat("CREATED_ON:{0}\t", this.CREATED_ON);
        retStr.AppendFormat("MODIFIED_ON:{0}\t", this.MODIFIED_ON);
        return retStr.ToString();
    }
}

Select

// プロバイダの情報を取得
var provider = DbProviderFactories.GetFactory(ConfigurationManager.ConnectionStrings[connectionName].ProviderName);
// 接続情報取得
using (var connection = provider.CreateConnection())
{
    // 接続文字列をApp.configから取得し設定
    connection.ConnectionString = ConfigurationManager.ConnectionStrings[connectionName].ConnectionString;
    try
    {
        // 接続開始
        connection.Open();
        // トランザクション開始
        using (var transaction = connection.BeginTransaction())
        {
            // Select文作成
            var sql = @"SELECT * FROM USER_MASTER WHERE USER_ID = :USER_ID";
            // バインド変数用インスタンス作成
            var bindObj = new USER_MASTER() { USER_ID = "0001" };
            // Select文実行
            var rows = connection.Query<USER_MASTER>(sql, bindObj, transaction);
        }
    }
    finally
    {
        // 接続切断
        connection.Close();
    }
}

Insert

// プロバイダの情報を取得
var provider = DbProviderFactories.GetFactory(ConfigurationManager.ConnectionStrings[connectionName].ProviderName);
// 接続情報取得
using (var connection = provider.CreateConnection())
{
    // 接続文字列をApp.configから取得し設定
    connection.ConnectionString = ConfigurationManager.ConnectionStrings[connectionName].ConnectionString;
    try
    {
        // 接続開始
        connection.Open();
        // トランザクション開始
        using (var transaction = connection.BeginTransaction())
        {
            try
            {
                // Insert文作成
                var sql = @"INSERT INTO USER_MASTER ( USER_ID, DEPT_NO ) VALUES ( :USER_ID, :DEPT_NO )";
                // Insert用インスタンス作成
                var insertObj = new USER_MASTER() { USER_ID = "9999", DEPT_NO = "9999" };
                // Insert文実行
                var result = connection.Execute(sql, insertObj, transaction);
                // コミット
                transaction.Commit();
            }
            catch
            {
                // ロールバック
                transaction.Rollback();
                throw;
            }
        }
    }
    finally
    {
        // 接続切断
        connection.Close();
    }
}

Update

接続やトランザクション周りはInsertと同じなので割愛。

// コネクションやトランザクション関係の前処理(省略)
// Update文作成
var sql = @"UPDATE USER_MASTER SET USER_NAME = :USER_NAME WHERE USER_ID = :USER_ID";
// Update用インスタンス作成
var updateObj = new USER_MASTER() { USER_ID = "9999", USER_NAME = "HOGE" };
// Update文実行
var result = connection.Execute(sql, updateObj, transaction);
// コネクションやトランザクション関係の後処理(省略)

Delete

// コネクションやトランザクション関係の前処理(省略)
// Update文作成
var sql = @"DELETE FROM USER_MASTER WHERE USER_ID = :USER_ID";
// Delete用インスタンス作成
var deleteObj = new USER_MASTER() { USER_ID = "9999"};
// Update文実行
var result = connection.Execute(sql, deleteObj, transaction);
// コネクションやトランザクション関係の後処理(省略)


各DBに依存せず使用できそうですし、簡単に使用できて良いですね。
でも、毎回コネクションやトランザクション関係のお決まりとなっているコードを
書くのは非常につらいので、これらはフレームワーク化(ライブラリ化)し、
隠蔽してやる必要がありそうです。

Oracle Managed Driverのインストール方法(NuGet)

NuGetからOracle Managed Driverをインストールする方法を
初めて知ったので、メモがてら記事に残します。
(今まではggってDLしてインストールしていた。)

インストールするには、以下のコマンドを
パッケージマネージャコンソールで実行します。

Install-Package Oracle.ManagedDataAccess

www.nuget.org


これだけです。


インストールが完了すると、App.Config内へいろいろと追記されます。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="oracle.manageddataaccess.client"
      type="OracleInternal.Common.ODPMSectionHandler, Oracle.ManagedDataAccess, Version=4.121.2.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
    </configSections>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2"/>
    </startup>
    <system.data>
        <DbProviderFactories>
            <remove invariant="Oracle.ManagedDataAccess.Client"/>
            <add name="ODP.NET, Managed Driver" invariant="Oracle.ManagedDataAccess.Client" description="Oracle Data Provider for .NET, Managed Driver"
                type="Oracle.ManagedDataAccess.Client.OracleClientFactory, Oracle.ManagedDataAccess, Version=4.121.2.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
        </DbProviderFactories>
    </system.data>
    <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            <dependentAssembly>
                <publisherPolicy apply="no"/>
                <assemblyIdentity name="Oracle.ManagedDataAccess" publicKeyToken="89b483f429c47342" culture="neutral"/>
                <bindingRedirect oldVersion="4.121.0.0 - 4.65535.65535.65535" newVersion="4.121.2.0"/>
            </dependentAssembly>
        </assemblyBinding>
    </runtime>
    <oracle.manageddataaccess.client>
        <version number="*">
            <dataSources>
                <dataSource alias="SampleDataSource"
                    descriptor="(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=localhost)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=ORCL))) "/>
            </dataSources>
        </version>
    </oracle.manageddataaccess.client>
</configuration>


タグ内にTNS_ADMIN情報の設定を行うこともできます。

    <oracle.manageddataaccess.client>
        <version number="*">
            <!--ここから  -->
            <settings>
                <setting name="TNS_ADMIN" value="C:\oraclexe\app\oracle\product\11.2.0\server\network\ADMIN\" />
            </settings>
            <!-- ここまでがTNS_ADMIN情報 -->
            <dataSources>
                <dataSource alias="SampleDataSource"
                    descriptor="(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=localhost)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=ORCL))) "/>
            </dataSources>
        </version>
    </oracle.manageddataaccess.client>


オンコーディングでTNS_ADMIN情報を設定する方法もあった気がしたけど、
それは思い出し次第追記ということで...

Form上の全コントロールを列挙する方法(.Net、WinForm)

Form上の全コントロールを列挙する方法です。
全コントロールに対し何かを設定したい場合に有効だと思います。
(共通のイベントを設定したい等。)

実装のサンプルコード(C#)は下記の通りです。

List<Control> controlList = new List<Control>();
Form f = new Form();
RecursiveControlSearch(f, controlList);

//コントロールを再帰的に検索し、resultListへ見つけたコントロールを詰める
private void RecursiveControlSearch(Control ctrl, List<Control> resultList)
{
    resultList.Add(ctrl);
    foreach(Control obj in ctrl.Controls)
    {
        RecursiveControlSearch(obj, resultList);
    }
}


LINQを使用したらもっと良い感じに書けそうな気がしたけども、
思いつかないのでこんな感じで。

Visual Studio Community 2017インストールメモ

Visual Studio Community 2017をインストールしたので、
インストール時の構成等のメモとして記事を書いておきます。

構成はこんな感じです。
f:id:j_levia:20170318184915p:plain
f:id:j_levia:20170318184924p:plain

使いそうな感じのをインストールするスタイルで。

.NETによるモバイル開発のインストール
Google Android エミュレーターですが、除外しています。
除外理由は、実機デバッグで補えば良い上に容量をくうので。
(他には、後からインストール可能だし...)
f:id:j_levia:20170318185407p:plain

個別のコンポーネントや言語パックについては、何も変更していません。


Visual STudio Community 2017を少し触ってみた感想ですが、
2015と比べて軽く、サクサク動くので気持ちいいですね。

これから、新しい機能を触っていこうと思います。



最後に、最初にインストールした時は起動しなかったのは何だったのだろう...
(再インストールしたら正常に起動した。)

Alt+Tab押下時のメニューにFormを表示させなくする方法(.Net)

Alt+Tab押下時のメニューにFormを表示させなくする方法です。
下記条件を満たすと、Alt+Tab押下時のメニューにFormに表示されなくなります。

1. タスクバーに表示させなくする
2. 拡張ウィンドウスタイルにWS_EX_TOOLWINDOWを指定する

それぞれ設定、実装方法のサンプルコード(C#)は下記の通りです。


1. タスクバーに表示させなくする

Form f = new Form();

f.ShowInTaskbar = false; //デザイナ上からも設定可


2. 拡張ウィンドウスタイルにWS_EX_TOOLWINDOWを指定する

// Formクラス内に実装
const int WS_EX_TOOLWINDOW = 0x00000080;
protected override CreateParams CreateParams
{
    get
    {
        CreateParams cp = base.CreateParams;
        cp.ExStyle = cp.ExStyle | WS_EX_TOOLWINDOW;
        return cp;
    }
}


追記
上記の2について、Formのプロパティを設定することでも対応可能でした。
コードは下記の通り。

Form f = new Form();

f.FormBorderStyle = FormBorderStyle.FixedToolWindow; //サイズ変更不可
f.FormBorderStyle = FormBorderStyle.SizableToolWindow; //サイズ変更可