生きることは簡単です

日々細々と生きています

SQLServerで「オブジェクト 'xxxx' は 列 'xxxx' に依存しています」のエラーが出る

マイグレーションを実行したら出たエラーで、解決にちょっと時間が掛かったので備忘録を兼ねて。

エラーの全文はこんな感じ。

オブジェクト 'xxxx' は 列 '(カラム名)' に依存しています

(SQL文) は失敗しました。1 つ以上のオブジェクトがこの 列 を参照しています。

さっそく検索にかけてみると、エラーに記載のあるカラム名が何かしらの制約を持っているということらしい。ということなので、とりあえず主キー制約や外部キー制約に設定されていないかを確認してみました。

 

...が、どうやら主キー・外部キー制約はない様子。「どういうこと??」と試行錯誤したところ、該当のカラムにデフォルト値が設定されていました。デフォルト値も制約という括りに含まれるのね...。これを解除してあげたところ、エラーに引っかからなくなりました。

ということなので、記事のエラーが出た場合、主キー・外部キー制約 + デフォルト値を確認していただいて、何かしらが入っていた場合は外してあげると動くようになるとおもいます。

DB周りはまだまだ難しいですな。

 

値代入時のイコールのインデントを揃える派

複数行に渡り値の代入を行う際、ガタガタになりがちなイコールのインデント。

double price = 100;
int productNo = 1;
string productName = "Drink"
DateTime buyYmd = new DateTime(2021, 1, 1)

エンティティフレームワークなんかを使ってると、数十行に渡ってカラムに値を代入することが多いんですよ。カラム名も長さがマチマチなので、結構見た目がガタガタになって見る気が失せるんですよね。

可読性はコードを書く上で大切だと説かれてますが、こういうところは個人の好みが出るようで、あんまりイコールのインデントを揃えている人を見たことがない。おそらくですが、手間の割にリターンがあまり大きくないからだと思います。せいぜいちょっと見やすくなる程度で、省いたところで大打撃を受けることはないからだと思います。また、一括で揃えるような自動補完的な機能がVisualStudioに備わってないからってのもあると思います。波かっこなんかはエンターを叩くだけで適したインデントで改行されますが、ああいう便利機能がないのも大きいかと(少なくとも私は知らないです)

私は断然揃える派です。昔読んだリーダブルコードに「イコールのインデントも揃えるとイイネ!」みたいなことが書いてあって、それをマネし始めたら板についてきた感じです。

double price     = 100;
int productNo     = 1;
string productName   = "Drink"
DateTime buyYmd      = new DateTime(2021, 1, 1)

ただ、VisualStudioを使っていると、インデントを揃えるために打ったスペースが強制的に削除されることがあるんですよ。
主にセミコロンを打った時ですかね。Ctrl+Zで戻すとインデントだけもとに戻るんですが、いちいちやるのは結構めんどい。
調べてみるとスペースの自動削除を抑止する機能がついているらしい。
www.ipentec.com
上記のサイトのVsiualStudioは結構古いですが、同じような操作で機能をONにできます。
ただ、VisualStudio2019の場合、[行間]という項目は存在せず、[スペース]という項目の中に該当の機能が入っています。
この機能をONにすることで、せっかく整えたインデントが何かの拍子に吹き飛ぶ心配をしなくて済むわけですね。ただし、自分以外の第三者ソースコードに手を入れた際、ほぼ確実にインデントがぶっ壊れた状態でプッシュされるんですな、これが。デフォで勝手にインデントが削除されるから、まあ仕方ないとは思うんですけどね...。せっかくきれいになっているのであれば、Ctrl+Zのワンプッシュで綺麗な状態を維持し続けてほしいんですが、まあ叶わぬ願いですな。

【C#】日付(DateTime)が年始から数えて何週目かを取得する

仕事で必要になって作ったメソッド。ちなみに日曜始まりで計算します。

public static int GetWeekCount(DateTime dt)
{
    DateTimeFormatInfo dfi = DateTimeFormatInfo.CurrentInfo;
    Calendar cal = dfi.Calendar;
    return cal.GetWeekOfYear(dt, dfi.CalendarWeekRule, dfi.FirstDayOfWeek);
}

DateTime型を引数で受け取り、それをGetWeekOfYearメソッドに横流すると、戻り値で週の数が返ってくるというとても単純な仕組み。
ただまあ、年始からの週数を取りたいことってあんまりない気がしていて、実用性がイマイチかな...と思ったのでオマケでもう一本。

特定の日付が2つ渡すと、その期間を週数で返すというメソッド。
日数を7で割った後、切り上げを行っています。経過した週数であれば切り捨てですが、その日付が何週目に属しているのかを知るのであれば切り上げですかね。

public static int GetPeriodWeekCount(DateTime startDt, DateTime endDt)
{
     // startDtがendDtより大きい場合は不正な値なので一律1を返す
     if (startDt > endDt) return 1;
     var weekNum = (endDt - startDt).TotalDays / 7;
     return weekNum == 0 ? 1 : Math.Ceiling(weekNum);
}

"ストア プロバイダー インスタンスで 'get_ProviderFactory' メソッドを呼び出した後に NULL が返されました"の対処法

エンティティフレームワークOracleに接続してアレコレしていたんですが、ある日急に下記のエラーが出て微動だにしなくなりました。

System.Data.Entity.Core.ProviderIncompatibleException: 型 'System.Data.OracleClient.OracleConnection' のストア プロバイダー インスタンスで 'get_ProviderFactory' メソッドを呼び出した後に NULL が返されました。ストア プロバイダーが正しく機能していない可能性があります。

 例外はBeginTransactionでOracleとの接続を行おうとしているコードで発生していました。接続すらできないって感じですね。

結論から書くと、原因はApp.Configに記載されているOracleの接続文字列にありました。プロバイダー名を接続文字列の要素に入れるんですが、それが下記のように書かれていました。

providerName="System.Data.OracleClient"

ちょっと調べてみましたが、System.Data.OracleClientはだいぶ前に廃止されたものらしいですね。
プロジェクトのNugetパッケージを確認したところ、Oracle.ManagedDataAccessが入っていたので...

providerName="Oracle.ManagedDataAccess.Client"

 こんな感じで書き直したら動くようになりました。もともとこうやって書いてたんですが、誰かが書き換えてテスト環境においてたみたいです。嫌な話ですね。

そもそもOracleとエンティティフレームワークの相性が抜群に悪く、SQLServerだとできることができなかったりします。既存のDBからコードファーストのモデルを作ろうとしても、接続でうまくいかないんですよね。Oracleが公式で配布しているNugetパッケージを使っても変なところで落ちたりします。

このあたりの情報って調べても全然出てこないので苦労するんですよね。少なくとも日本語の情報はほとんどないので、こういうときに英語ができればなって思います...。