前提・実現したいこと
LINQで取得するマスターのデータに詳細データを追加したい。
(下記のソースコードの)OwnersクラスのPetsプロパティーにJOINしたPetsテーブルのデータを付けて、LINQでSelectしたいと思っています。
※DBでのリレーションシップは考えておりません。
発生している問題・エラーメッセージ
マスターのデータだけ取得される。
該当のソースコード
C#
1 2class Owner 3{ 4 public string Id { get; set; } 5 public string FirstName { get; set; } 6 public string LastName { get; set; } 7 public IEnumerable<Pet> Pets{ get; set; } 8} 9 10class Pet 11{ 12 public string Id { get; set; } 13 public string OwnerId { get; set; } 14 public string Name { get; set; } 15} 16 17 18var entity = (from o in context.Owners 19 join p in context.Pets 20 on o.Id equals d.OwnerId into gj 21 from gjp in gj.DefaultIfEmpty() 22 select o).FirstOrDefault(); 23 24
試したこと
C#
1var entity = (from o in context.Owners 2 join p in context.Pets 3 on o.Id equals d.OwnerId into gj 4 from gjp in gj.DefaultIfEmpty() 5 select new Owner{o,Pets=gj}).FirstOrDefault();
みたいな感じが出来ればいいのですが。。。
ぐぐって、色々サンプルなどを見ると、select new がほとんどでした。
そして、匿名型上でプロパティーを作り、各項目を代入していました。
ここに載せているソースコードではOwnerのプロパティ(カラム)は少ないですが、
多い場合、全ての列を書くのはあほくさい、というか、バグの温床やメンテ地獄になるかと思いますので、今回の質問をさせていただきました。
補足情報(FW/ツールのバージョンなど)
Visual Studio 2019
EF Core 2.2
.NET Standard 2.0.3
リレーションシップを考えたらいいと思います。
使いもしない Owners クラスと Pets クラスが無駄です。
もし使うのであれば、Pets クラスに Owners クラスを保持するプロパティを持たせれば解決です。Owners クラスに Pets クラスのリストを保持するプロパティを持たせると更に利便性が上がります。
匿名型には色々制限があるので、メインに使うものではありません。
外部結合した結果を取得したいのだと理解してますが、具体的にどういう項目なのですか? それを書いてもらえないと・・・
> Zuishinさん
> Owners クラスに Pets クラスのリストを保持するプロパティを持たせると更に利便性が上がります。
これについては、
public IEnumerable<Pet> Pets{ get; set; }
という形で、用意してます。
また、逆参照は必要がないと考えていますので、PetsクラスにはOwnersクラスの情報を持たせるプロパティーは定義しておりません。
> public IEnumerable<Pet> Pets{ get; set; }
それ、そもそも文法的に間違ってませんか? 文法的に合っていても、何の役にも立たないかと思いますけど。
> SurferOnWwwさん
いつも(勝手にお世話になっていまして、)ありがとうございます。
はい、外部結合の結果として、Ownersクラスを返す関数になっています。
その詳細データである、Petsクラスの配列( public IEnumerable<Pet> Pets{ get; set; })をプロパティーとして用意していますので、そこに外部結合のデータを代入したいと思っています。
LINQでJoinしているので、データはSelect newなどしなくても、(from o in context.Ownersのoに)入ってくるのかなと思っていたのですが、ウオッチ式で見ても入っておらず。。。
今書いてておもったのですが、結局、oはcontext.Ownersなので、JOINする前のデータしか入らないのかなと。
であれば、joinした後である、on o.Id equals d.OwnerId into gjのgjだったらいいのかと試しましたが、PetsのListが、取得されるだけで、Ownersクラスの情報は付いていませんでした。
なので、select のところで、from o in context.OwnersのoのPetsプロパティーにgjをそのまま代入できればなと思った次第なのですが、、、
用意しているなら、そこに追加すれば匿名クラスを使う必要など全く無いと思います。
普通は join を使う必要すらなく、それぞれのエンティティーを Load するだけで使えます。
> SurferOnWwwさん
>> public IEnumerable<Pet> Pets{ get; set; }
>それ、そもそも文法的に間違ってませんか? 文法的に合っていても、何の欲にも立たないかと思いますけど。
ビルドは通っていますので、文法的には間違っていないと思うのですが。。。
それとも、何か考え間違いしているのでしょうか。。。
> Zuishinさん
(用意しているので、)その追加する方法がわからないという状況に陥っています。
このコードではプロパティを用意しているだけで実装が無いので、追加できません。
リレーションシップを張れば使えるようになります。
張らないのなら自分で実装する必要があります。
SurferOnWww さん、そこは EntityFramework が依存性注入してくれること前提のコードです。リレーションシップを張ってないらしいので単なる無駄プロパティになっているようですが。
> ビルドは通っていますので、文法的には間違っていないと思うのですが。。。
IEnumerable<Pet> の Pet はアップされてるコードを見る限りどこにも定義されてないようですが・・・
Zuishin さん、書かれているプロパティは、上に書きましたが Pet が定義不明ですし(class Pets が class Pet の間違い?)、ましてやナビゲーションプロパティでもなさそうですし(virtual がないので)、意味不明&役に立たないと思うのですが。ビルドは通るとのことなので、質問に書いてないところに何かがあるのかもしれませんけど。
質問者さん、上にも書きましたが外部結合の結果、何を取得できればいいのですか? 詳しく書いてください。
SurferOnWww さん、おっしゃる通りです。脳内補完しながら読んでしまいました。
質問者さんはいなくなってしまったようですが、
> ※DBでのリレーションシップは考えておりません。
では何ともならないようですので、そこは考え直してもらうとして(リレーションを張ってナビゲーションプロパティを使うようにして)、案を回答欄に書いておきます。
SurferOnWwwさん、Zuishinさん
脳内変換申し訳ないです。
public IEnumerable<Pet> Pets{ get; set; }
DBに保存されているPetのデータをOwnerと一緒に読み込めればいいという話なのですが、そういうことでは足りないでしょうか。
SurferOnWwwさん
すみません。山籠もりしていました。(嘘ですが、貝になって考えていました。)
やはり、リレーションシップはしないで、という条件でどうにかならないか、という事が知りたいので、EF coreの仕様上どうにもならないという、話でしたら、致し方なしという事になるのですが。。。。
そうですね。DB を適切に設定すれば Pet と Owner の関連付けを自動的にやってくれるので、遅延読み込みを使用してもしなくても始めから使用可能になっています。
Load をお勧めしたのは N+1 問題対策ですが、問題が起こっていなければ遅延読み込みでも構いません。
SurferOnWwwさん
SurferOnWwwさんの2019/11/03 19:56の投稿でご指摘のあるクラス名の修正を先ほど修正しました。
混乱させて申し訳ありません。
> 始めから使用可能になっています。
これは語弊があるので補足します。遅延読み込み設定された時は必要となった時点でデータが読み込まれます。そうでない時は Load などで最初にデータを読み込んでおく必要があります。
Zuishinさん
ありがとうございます。
> それぞれのエンティティーを Load するだけで使えます。
は、自分の回答が出て、先ほど再度読み直して、理解できました。(汗
(どういう意味のLoadかと)
さらに、補足分(2019/11/07 15:01)に関しても、今なら理解できます。 o(゚▽゚o)(o゚▽゚)oニパ
回答3件
あなたの回答
tips
プレビュー

