ASP.NET MVCでCRUD ツイートレスポンスをDBに登録する
概要
前回の続きです。
kitigai.hatenablog.com
ツイートするとレスポンスを受け取ることができるので
そのレスポンス内容をDBに登録してみます。
いわゆるCRUDです。(Create Read Update Delete)
目次
実行環境
- Windows 10 Pro (バージョン:1709)
- Visual Studio Community 2015 Update3
- .NET Framework 4.5.2
ソース
ASP.NET MVCでCRUD
こちらの記事が大変参考になりました。
qiita.com
DB接続文字列の設定
DBに接続するための設定部分をいじります。
プロジェクト直下/Web.config
//改変前 <connectionStrings> <add name="DefaultConnection" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\aspnet-TweetTest-20180102122324.mdf;Initial Catalog=aspnet-TweetTest-20180102122324;Integrated Security=True" providerName="System.Data.SqlClient" /> </connectionStrings> //改変後 <connectionStrings> <add name="MyContext" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\aspnet-TweetTest-20180102122324.mdf;Initial Catalog=aspnet-TweetTest-20180102122324;Integrated Security=True" providerName="System.Data.SqlClient" /> </connectionStrings>
name部分のDefaultConnectionをMyContextに変更します。
ほかはいじっていません
自前で用意したDBは使用せず既存のDBを使用するので
この設定変更はいらないと思いしていなかったのですが
していない状態でうまくいかなかったので
参考にしたQiitaの記事通りに設定します。
Modelの準備
ツイートレスポンスを格納するためのモデルを用意します。
public class TweetResult { public int id { get; set; } public string tweet { get; set; } public string tweetId { get; set; } } public class MyContext : DbContext { public DbSet<TweetResult> TweetResults { get; set; } }
MyContextにて、物理テーブル(Members)にマップしています。*1
マップ?とは何ぞやって感じですが
TweetResultsテーブルと対をなすのはこのTweetResultモデルですって
明示するって感じであってますか?(ちゃんと調べる。)
テーブルの準備
順序が逆な気が超しますが、テーブルを作成します。
CREATE TABLE [dbo].[TweetResults] ( [id] INT IDENTITY (1, 1) NOT NULL, [tweet] NVARCHAR (MAX) NULL, [tweetId] NVARCHAR (MAX) NULL, CONSTRAINT [PK_dbo.TweetResults] PRIMARY KEY CLUSTERED ([id] ASC) );
とりあえず動けばいいやーで作ってたらこんなのになってしまった。
TweetのIDってLong型で返ってくるんですね・・・
Controllerに登録部分を作成
とりあえずController部分のソース
余計なコメントは気にしない
public class TweetController : Controller{ //DBコネクションのインスタンス?であってる? private MyContext db = new MyContext(); //...中略 //テーブルを参照する際、awaitを使用しているのでasyncに変更? public async Task<ActionResult> TweetPost(TweetViewModels tt){ //...中略 //ツイート後、レスポンス取得 CoreTweet.StatusResponse var res = tokens.Statuses.Update(status => DateTime.Now + " " + tt.TweetText); var tr = new TweetResult{ id = 1, tweet = res.Text, //ツイート内容 tweetId = res.Id.ToString() //ツイートID }; db.TweetResults.Add(tr); //テーブルに追加 db.SaveChanges(); //データの変更をコミット return View(res); } public ActionResult Result(){ var tr = db.TweetResults.ToList(); return View(tr); } }
参考記事にはControllerでいくつもContextを生成しないために
全体で使用できるよう定義しているのでそのまま真似します。
HomeController全体で利用するContextをdbとして定義。*2
ツイートのレスポンスからツイート内容とツイートIDを
TweetResultクラスに突っ込みます。
(※IDはほんとは自動インクリメントのインデックス番号にしたかった)
その作成したTweetResult(tr)をAddにてテーブルに追加します。
コミット
これでいいのかーと思いきや
SaveChangesを実行しないとDBコミットされないようです。
これで準備おっけ!
ツイートして登録されるか確認する
2018/01/08 18:40:30 aaaa
— あとらす (@Lychee_jam) 2018年1月8日
完璧。
エラーと格闘中に一覧表示のViewも作ったのでそっちでも確認してみる。
トラブルシュート
本当はここが書きたかった
まずはこれを見てくれ
こんなエラーが出ました。
There is already an object named '__MigrationHistory' in the database.
こいつに俺の3連休はつぶされた!!!!(大袈裟)
"__MigrationHistory"って名前のテーブル(オブジェクト?)はもうDBに存在するよーって言ってますよね?
作った覚えないんですがそれは・・・
とりあえずググる。
stackoverflow.com
うわあああああああ、苦手な英語のページしかヒットしなーい
接続文字列が変更されたから__MigrationHistoryって言うテーブルを再作成しなさい?
見たいな感じですかね?結局よくわからなかったんですよね
サーバーエクスプローラーを確認してみる
こいつか存在するからエラーが起きるなら消してみよう
削除後、実行するとうまくいきました。
そして再度確認すると__MigrationHistoryが再作成されていました。
想像
たぶんテーブルを手動作成の下りがいらなかった?
参考文献の中にコードファーストとかDBファーストなんて言葉が出てきたけど
モデルの中にDbContextを定義したら自動でテーブルが作成されたりします?
これ、要検証でまだ検証とか調べたりとかはしてません。