くりーむわーかー

プログラムとか。作ってて ・試しててハマった事など。誰かのお役に立てば幸いかと。 その他、いろいろエトセトラ。。。

2017年04月

.netMVCのGDI+エラーをどうにか回避したい その2

以前、GDI+のエラーを回避したい的なのを書いた。その続き。

前回書いたものは今のとこ大丈夫そうなんだけど、使用してるライブラリで内部でDrawing使ってるやつもダメになってるね。当たり前だけども。詰みかな?

ちなみに、エクセル操作するEPPlusってやつを使って、エクセルに画像を貼る際に、Drawing使ってるらしくやられました。

結構、根が深いんじゃなかろーか。さてどうしましょう。

マイクロソフトさんに頑張っていただくしかなかね。。。

.netMVCのGDI+エラーをどうにか回避したい

この前、.NetMVCのWebアプリでSystem.Drawing使って画像作るとGDI+エラーが出るっていうの書いた。

System.Drawing使えないとなると結構しんどいので、他のライブラリを使ってみる。画像っていったらやっぱりImageMagickかしらね。ちょっと調べてみると結構色々あるのね。↓のやつら。

ImageSharpなんか良さげなので使ってみよーかと思ったら、.net4.5は対応外だそうです。残念。対応したら使ってみよ。

で、結局ImageMagick(Magick.NET)に落ちついたわけですが。Nugetでインストールして↓の感じで作ってみた。

//全部をImageMagickでやるのはしんどかったので、
//エラーが出るところだけ書き換え
Color c = Color.FromArgb(0xFF, Color.FromArgb(Convert.ToInt32("0xD9333F", 16)));
Font f = new Font("MS 明朝", 12);
using (Bitmap img = new Bitmap(100, 64))
{
    using (Graphics g = Graphics.FromImage(img))
    using (Pen pen = new Pen(c))
    {
        g.DrawLine(pen, 0, 0, 100, 0);
        g.DrawString("Something Text...", f, new SolidBrush(c), 5, 5);
    }
    string folder = "適当なフォルダ";
    string filename = "適当なファイル名";
    fullFileName = System.IO.Path.Combine(folder, filename);
    
    //GDI+エラーが出るのは保存のところ ↓の感じ
    //img.Save(fullFileName, ImageFormat.Png);
    
    //↑の保存をImageMagickを使って保存に変える
    using (ImageMagick.MagickImage image = new ImageMagick.MagickImage(img))
    {
        image.Format = ImageMagick.MagickFormat.Png;
        image.Write(fullFileName);
    }
}

今のところエラーは出てないけど、様子見なり。

で、保存の部分だけ使ったのですが、ホントはImageMagickで日本語のテキスト出せなかったので保存だけに逃げました。

コマンドラインから使う場合は出す方法が色々見つかるんだけど、.netから呼ぶ場合のがどうしてもわからなかった。何となく、フォントの指定がうまくできない。気が向いたら調べてみよう。

端末変えたら500.21のエラー

最近、PC変えたんですけど、ローカルのIISで.netのWebアプリ動かしたときに500.21エラーが出た。

sample

ManagedPipelineHandlerってなんぞ?

調べてみると、.netが完全にはインストールされてないらしい。SDK入れたような気がするんですが・・・。

↓のコマンドでインスコ。管理者で実行したコマンドプロンプトじゃないときっとダメ。

C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis -i

↑で治った。

SQLServer 断片化と平均ページ密度を調べるクエリ

SQLServerで全DB・全テーブルの断片化と平均ページ密度の調査する時のクエリ。

断片化と平均ページ密度については↓のサイトでどうぞ。
https://blogs.msdn.microsoft.com/jpsql/2011/10/16/337/

SET NOCOUNT ON;

declare @CR_DATABASE_ID AS INT
declare @CR_DBNAME AS NVARCHAR(200)
declare @WKSTR AS VARCHAR(20)

--//DBとテーブルのリスト用
create table #WKTBLLIST
(
database_id int
,object_id int
,DB名 nvarchar(200)
,テーブル名 nvarchar(256)
)
--//結果保存用
create table #RESULT
(
database_id smallint
,object_id int
,table_object_id int
,index_id int
,DB名 nvarchar(256)
,テーブル名 nvarchar(256)
,[断片化率] float
,[平均ページ密度] float
,ページ数 bigint
,レコードカウント bigint
)

--//DB毎に繰り返し
declare CUR_1 cursor for
select top 1 database_id,name from sys.databases 
order by name

open CUR_1

FETCH NEXT FROM CUR_1
INTO    @CR_DATABASE_ID,@CR_DBNAME

while(@@FETCH_STATUS=0)
begin
	--//DB毎にテーブルの一覧を保存する
    set @WKSTR = cast(@CR_DATABASE_ID as varchar(10))
    exec(
    'use ' + @CR_DBNAME + ';' +
    'insert #WKTBLLIST '+
    'select '+ @WKSTR +',object_id,'''+@CR_DBNAME+''',name ' +
    'from sys.tables ' +
    );

    FETCH NEXT FROM CUR_1
    INTO    @CR_DATABASE_ID,@CR_DBNAME
end

Close CUR_1
DEALLOCATE CUR_1

declare @CR_OBJECT_ID AS INT
declare @CR_TABLENAME AS NVARCHAR(256)

--//上で保存したDB/テーブルのリストで繰り返し
declare CUR_1 cursor for
select database_id,object_id,DB名,テーブル名 from #WKTBLLIST
order by database_id,テーブル名

open CUR_1

FETCH NEXT FROM CUR_1
INTO    @CR_DATABASE_ID,@CR_OBJECT_ID,@CR_DBNAME,@CR_TABLENAME

while(@@FETCH_STATUS=0)
begin
	--//テーブル毎に断片化率を取得して結果テーブルに保存
    insert #RESULT
    select 
    database_id
    ,object_id
    ,@CR_OBJECT_ID
    ,index_id
    ,@CR_DBNAME as DB名
    ,@CR_TABLENAME as テーブル名
    ,avg_fragmentation_in_percent as [断片化率]
    ,avg_page_space_used_in_percent as [平均ページ密度]
    ,page_count as ページ数
    ,record_count as レコードカウント
    from sys.dm_db_index_physical_stats(@CR_DATABASE_ID,@CR_OBJECT_ID, NULL, NULL , 'DETAILED')

    FETCH NEXT FROM CUR_1
    INTO    @CR_DATABASE_ID,@CR_OBJECT_ID,@CR_DBNAME,@CR_TABLENAME
end

Close CUR_1
DEALLOCATE CUR_1

--//断片化してるインデックスを調査
select * from #RESULT
where 断片化率 > 30 --Microsoftの目安値
and ページ数 > 50 --ページ数が少ない奴は見てもしょうがないと思う

--//平均ページ密度が低下してるインデックスを調査
select * from #RESULT
where 平均ページ密度 < 60--60%はなんとなく
and ページ数 > 50 --ページ数が少ない奴は見てもしょうがないと思う

--//全部の結果
select * from #RESULT

SET NOCOUNT OFF;

あとは↓の感じで再構成か再構築する

--再構成はこっち
ALTER INDEX ALL ON [テーブル名] REORGANIZE WITH(LOB_COMPACTION=ON);
--再構築はこっち
ALTER INDEX ALL ON [テーブル名] REBUILD WITH(ONLINE=OFF);

再構成(REORGANIZE)はリーフレベル:一番下位のページしかやらないらしく、大本がそもそもイカれてる場合は意味無い。その場合は再構築(REBUILD)する。ただし、REBUILDは処理してるインデックス単位にロックするらしいので、実行してる最中はテーブルはさわっちゃだめ。

参考サイト

断片化について
https://blogs.msdn.microsoft.com/jpsql/2011/10/16/337/

インデックスの再構築 (rebuild) と再構成 (reorganize) の違い
https://blogs.msdn.microsoft.com/jpsql/2013/02/28/977/

Reorganize and Rebuild Indexes
https://msdn.microsoft.com/ja-jp/library/ms189858.aspx

ALTER INDEX (Transact-SQL)
https://msdn.microsoft.com/ja-jp/library/ms188388.aspx

sys.dm_db_index_physical_stats (Transact-SQL)
https://msdn.microsoft.com/ja-jp/library/ms188917.aspx

問合せ