エンティティフレームワークと一意の制約を操作するときのいくつかの明白でないハッキングについて

画像

数年前、木々が大きくて緑だったとき、 邪悪な寄付者が私のところに来て言った。 私は非常に奇妙なプロジェクトで同僚を助けなければなりませんでした。



つまり、アナリストがお気に入りのMS Officeパッケージで月に1回構成する数字の束を想像してください。 そして、月に一度、これらの数字を噛んでMS SQLを実行しているデータベースにロードする必要がありました。



そしてもちろん-このメガツールは迅速に行われなければなりませんでした。 それからマレー人かインディアンのどちらかを安いサポートに転送します。 そのため、できるだけ明確にすることも推奨されました。







どのようにして問題を解決し始めましたか



画像

悪のアフィリエイトは、対応するレポートに非常に多くの列があり、Excelが3文字の名前を付けている場合、手に入れるのではなく、生活を簡素化することにしました。 また、古代のデータベースには膨大な数のテーブルがあり、列の数が驚くほど多いものもあります。



したがって、DBはこのように行われました。DBはビジュアルスタジオをすり抜け、エンティティフレームワーク用のコードの巨大なフットクロスを取得しました。 ジグソーでのこぎり引きと、値に100の質問を含む準備済みステートメントをコンパイルする代わりに(...)-エンティティオブジェクトの通常の塗りつぶしの後にcontext.SaveChanges()が続きます。



私は注意します-正しい決定。 そして、時期尚早な最適化は悪であることが知られています。



このアプローチに付属したもの



画像

焦げた匂いがする。 私は台所に急ぎ、latkiから肉を取り出します。 焼けたものを両手剣で切り、すぐにそれを飲み込みます。ウゴレックが部屋に飛び込んできました。 ホット! しかし、私は描きます。

「それは何ですかマスター」

-蒸し暑い中国人。 最新の流行!

-洪水しないでください-あなたは辞書からのみファッションについて知っています、-それは試みます。 「本当に美味しい!」





それは紙の上で滑らかでした...ユニークな制約、すべてのtsiferkiが食べることに同意したわけではありません。



驚くべき事実-エンティティフレームワークがデータベースレベルの例外を受け取ると、 Microsoftの推奨に基づいて実行中のイノシシになります。このコンテキストを撮影して次のコンテキストを作成する方法は1つしかありません。 この場合、これはマスターを古いコンテキストから引き出すか、再作成する必要があることを意味し、catch()のすべてのフィールドをコピーしないことをお勧めします。



そしてもちろん、それをより面白くするために-異なるコンテキストのオブジェクトを混在させることはできません。



多くの場合、レクリエーションをサポートすることは重要なことであり、マレー人がこれらのハッキングをどのようにサポートするかは大きな問題です。



そしてこの瞬間、 これらの悪霊は鉄とはんだごてをもたらしました! 私に届いた。



なすべきこと



画像

カラペットはinしている。

-有害です! 彼らは100キログラムのエネルギーを要求しましたが、どれだけのエネルギーでしょうか! あなたはそう言う-あなたは多くを必要とする、なぜカラペットをだますか? 申し訳ありませんが、5トンが必要です-Karapetに5トン与えてください。それらは有害で有害です!



判明したように、CancelChangesエンティティはエンティティフレームワークで提供されていません。 そして、その存在は複雑にならないチャンスを与えます。



ご想像のとおり、私は発明しなければなりませんでした。



初めに、アプローチを決定します-コンテキストの周りの荒削り、そのような悲しい結果につながる非常に悪い歯の要素をキャッチします。 そして-文脈から彼を捨てます。 もちろん、これからのデータはデータベースに表示されませんが、コンテキストは引き続き機能します。これが必要です。 そして、アナリストが湾曲したデータを処理できるようにします。私たちの仕事は、データが見つかった場所にデータを書き込むことです。



どこに置くか?


画像

-Afa、一緒に自分自身を引きます!

私は腕に身を包み、バイオグレイブで床から引き剥がします。

-私はそれを取った。 どこに置くか?





例では、挿入が最も自明ではないことに注目しました。 更新も同様に解析されます。 フットクロスは上記とあまり変わらず、更新を追跡するのが簡単なので、フットクロスを持っていません。 Deleteはありません。これは妄想であり、銀行家の仲間です。データベースから何かを削除するにはどうすればよいですか? いやいや!



マニュアルを喫煙して次のようにグーグルで調べた後、次のデータ構造を定義します。



class MyEntry { public EntityObject entity; // entity object,  public string name; //    EF public Dictionary<string, EntityKey> refmap; // foreign keys -  - ,   //         FK      public Dictionary<string, EntityObject> objmap; //   public Dictionary<EntityObject, string> keymap; //     public MyEntry(string s, EntityObject o) { entity = o; name = s; refmap = new Dictionary<string, EntityKey>(); objmap = new Dictionary<string, EntityObject>(); keymap = new Dictionary<EntityObject, string>(); } }
      
      







これで魔法をかけることができます。 これが決定方法です-最後のSaveChanges()の後にコンテキストに追加されたもの:



  // t  derived class  EntityContext var added = t.ObjectStateManager.GetObjectStateEntries(EntityState.Added);
      
      







これで、内容を判断し、詳細な試行のためにシフトできるようになりました。 そのようなもの。



  List<MyEntry> allDataToProceed = new List<MyEntry>(); //     foreach (var a in added) { //  EF        .  //      if (!(a.IsRelationship)) { //   -    "Foo", Foo a MyEntry e = new MyEntry(a.EntitySet.Name, a.Entity); allDataToProceed.Add(e); //     foreign keys    IEnumerable<IRelatedEnd> relEnds = ((IEntityWithRelationships)a.Entity).RelationshipManager.GetAllRelatedEnds(); foreach (var rel in relEnds) { //     FKs List<EntityObject> fks = new List<EntityObject>(); foreach (var obj in rel) fks.Add((EntityObject)obj); //         -  var relname = rel.RelationshipName; if (fks.Count == 1) { //   -    ,   if (fks[0].EntityKey.EntityKeyValues != null) e.refmap[relname] = fks[0].EntityKey; else { //     -  , //    .  -   //      //       FK     e.keymap[fks[0]] = fks[0].EntityKey.EntitySetName; e.objmap[relname] = fks[0]; } } } } }
      
      







残っているのは、コンテキストを生き返らせることだけです。



  //       foreach (var a1 in added) a1.Delete(); t.SaveChanges();
      
      







そして、悪魔払いのセッションを開始します-そして、それがここでクロールされ、最も重要なこと-それをどこに置くか。



自宅でも叫ばないでください


画像

スクリーンは圧力から破裂します。 私はほうきを取り、断片を集めます-私は遠征のリーダーです。 コーナーは何かを言いたがっています-彼が3キロメートルの深さで持っているなんてきしむような声。 彼に言います

-家で叫ぶな。

考えて、私は追加します

「そして、家でも叫ぶな。」





最初に行う必要があるのは、外部キーを考慮することです。 オブジェクトがマスタースレーブチェーンの一部として作成されている場合、マスターとスレーブを別々に追加する必要はありません。そうしないと、参照整合性が損なわれる可能性があります。



  //           FK //       List<EntityObject> usedInRefs = new List<EntityObject>(); foreach (var a1 in allDataToProceed) { foreach (var dup in a1.objmap.Values) usedInRefs.Add(dup); } //   for (int j = 0; j < allDataToProceed.Count; ++j) { if (usedInRefs.Contains(allDataToProceed[j].entity)) { allDataToProceed.RemoveAt(j); --j; } }
      
      







そして最後に、事は小さいです-あなたが詰め込むことができるものをデータベースに詰め込むために残っています。 これを行うには、外部キーのコピーを復元し、コンテキストに追加します。 成功しましたか? 優れた、いいえ-これは私たちの悪い歯であることを意味します。



  //     -      foreach (var a1 in allDataToProceed) { try { //    FKs  master/slave IEnumerable<IRelatedEnd> relEnds = ((IEntityWithRelationships)a1.entity).RelationshipManager.GetAllRelatedEnds(); foreach (var rel in relEnds) { var relname = rel.RelationshipName; EntityKey key = null; //          EF //         if (a1.refmap.ContainsKey(relname)) key = a1.refmap[relname]; EntityObject o = key != null ? o = (EntityObject)t.GetObjectByKey(key) : null; //     -      // master/slave  if (o == null && a1.objmap.ContainsKey(relname)) { o = a1.objmap[relname]; if (a1.keymap.ContainsKey(o)) t.AddObject(a1.keymap[o], o); else o = null; } //    -    if (o != null) rel.Add(o); } //       t.AddObject(a1.name, a1.entity); t.SaveChanges(); } catch (Exception e2) { //        -     //      added = t.ObjectStateManager.GetObjectStateEntries(EntityState.Added); foreach (var a2 in added) a2.Delete(); //   -    ,      } }
      
      







出来上がり。 やった!



おそらく、このアプローチは誰かに役立つでしょう。



All Articles