Entity Framework 5での動的データの使用





こんにちは



ご存じのとおり、 .NET Framework 4.5のリリースバージョンは既にリリースされており、 Visual Studio 2012の最終バージョンもダウンロードできるようになっています。



ベータ版以降、新しいVisual Studioに精通し、リリース後、Visual Studioのrtmリリースと.NET Framework 4.5を実際に使用し始めました。

.NET Frameworkの新しいバージョンには、Entity Frameworkの新しいバージョンも含まれています。 すでに5番目。 より正確には、それはそこまで行きません-プロジェクトを作成するとき、NuGetリポジトリからファイルをアップロードします。 しかし、いずれにせよ、新しいプロジェクトはライブラリの正確に5番目のバージョンを使用します。



続行する前に、EF5の新機能と、このバージョンの使用を開始する理由を簡単に説明します。



Entity Framework 5.0の新機能





これは完全なリストではありませんが、これらの機能には非常に興味がありました。

イノベーションの詳細については、 こちらをご覧ください



タスクの本質



私のデータ管理プロジェクトの多くでは、ASP.NET Dynamic Dataに基づいて作成されたソリューションを使用しています(このソリューションの適用方法と、一般に、scaffoldテクノロジを実装するツールについては前に書きました )。 既に説明したように、Entity Frameworkの新しいバージョンでは、Database Firstモードを使用する場合でも、以前のようにObjectContextではなくDbContextクラスに基づいてコンテキストを生成するようになりました。 動的データは、ObjectContextが基本コンテキストクラスとして使用されることを前提としています。



この点で、ダイナミックデータを正しく操作するには、コンテキストの初期化と一部のコントロールの動作をわずかに変更する必要がありました。 Pranava Rastogiのブログでこのテーマに関する非常に良い記事を見つけました。



この情報は、Dynamic Dataを使用しており、Entity Frameworkの新しいバージョンへのアップグレードを計画している人にとって役立つと思います。



DbContextベースのコンテキストと対話するためのASP.NET動的データの構成



ダイナミックデータを新しい形式で正しく機能させるには、3つの簡単な手順を実行する必要があります。



1.プロジェクトルートのGlobal.asaxコードを変更する


DefaultModel.RegisterContext(() => { return ((IObjectContextAdapter)new YourContextType()).ObjectContext; }, new ContextConfiguration() { ScaffoldAllTables = true });
      
      







2. Dynamicdata \ Fieldtemplatesディレクトリの制御コードManyToMany.ascx.csを変更します


  protected override void OnDataBinding(EventArgs e) { base.OnDataBinding(e); object entity; ICustomTypeDescriptor rowDescriptor = Row as ICustomTypeDescriptor; if (rowDescriptor != null) { // Get the real entity from the wrapper entity = rowDescriptor.GetPropertyOwner(null); } else { entity = Row; } // Get the collection and make sure it's loaded var entityCollection = Column.EntityTypeProperty.GetValue(entity, null); var realEntityCollection = entityCollection as RelatedEnd; if (realEntityCollection != null && !realEntityCollection.IsLoaded) { realEntityCollection.Load(); } // Bind the repeater to the list of children entities Repeater1.DataSource = entityCollection; Repeater1.DataBind(); } public override Control DataControl { get { return Repeater1; } }
      
      







3. Dynamicdata \ Fieldtemplatesディレクトリの制御コードManyToMany_Edit.ascx.csを変更します




 protected ObjectContext ObjectContext { get; set; } public void Page_Load(object sender, EventArgs e) { // Register for the DataSource's updating event EntityDataSource ds = (EntityDataSource)this.FindDataSourceControl(); ds.ContextCreated += (_, ctxCreatedEnventArgs) => ObjectContext = ctxCreatedEnventArgs.Context; // This field template is used both for Editing and Inserting ds.Updating += DataSource_UpdatingOrInserting; ds.Inserting += DataSource_UpdatingOrInserting; } void DataSource_UpdatingOrInserting(object sender, EntityDataSourceChangingEventArgs e) { MetaTable childTable = ChildrenColumn.ChildTable; // Comments assume employee/territory for illustration, but the code is generic if (Mode == DataBoundControlMode.Edit) { ObjectContext.LoadProperty(e.Entity, Column.Name); } // Get the collection and make sure it's loaded dynamic entityCollection = Column.EntityTypeProperty.GetValue(e.Entity, null); // Go through all the territories (not just those for this employee) foreach (dynamic childEntity in childTable.GetQuery(e.Context)) { // Check if the employee currently has this territory var isCurrentlyInList = ListContainsEntity(childTable, entityCollection, childEntity); // Find the checkbox for this territory, which gives us the new state string pkString = childTable.GetPrimaryKeyString(childEntity); ListItem listItem = CheckBoxList1.Items.FindByValue(pkString); if (listItem == null) continue; // If the states differs, make the appropriate add/remove change if (listItem.Selected) { if (!isCurrentlyInList) entityCollection.Add(childEntity); } else { if (isCurrentlyInList) entityCollection.Remove(childEntity); } } } private static bool ListContainsEntity(MetaTable table, IEnumerable<object> list, object entity) { return list.Any(e => AreEntitiesEqual(table, e, entity)); } private static bool AreEntitiesEqual(MetaTable table, object entity1, object entity2) { return Enumerable.SequenceEqual( table.GetPrimaryKeyValues(entity1), table.GetPrimaryKeyValues(entity2)); } protected void CheckBoxList1_DataBound(object sender, EventArgs e) { MetaTable childTable = ChildrenColumn.ChildTable; // Comments assume employee/territory for illustration, but the code is generic IEnumerable<object> entityCollection = null; if (Mode == DataBoundControlMode.Edit) { object entity; ICustomTypeDescriptor rowDescriptor = Row as ICustomTypeDescriptor; if (rowDescriptor != null) { // Get the real entity from the wrapper entity = rowDescriptor.GetPropertyOwner(null); } else { entity = Row; } // Get the collection of territories for this employee and make sure it's loaded entityCollection = (IEnumerable<object>)Column.EntityTypeProperty.GetValue(entity, null); var realEntityCollection = entityCollection as RelatedEnd; if (realEntityCollection != null && !realEntityCollection.IsLoaded) { realEntityCollection.Load(); } } // Go through all the territories (not just those for this employee) foreach (object childEntity in childTable.GetQuery(ObjectContext)) { // Create a checkbox for it ListItem listItem = new ListItem( childTable.GetDisplayString(childEntity), childTable.GetPrimaryKeyString(childEntity)); // Make it selected if the current employee has that territory if (Mode == DataBoundControlMode.Edit) { listItem.Selected = ListContainsEntity(childTable, entityCollection, childEntity); } CheckBoxList1.Items.Add(listItem); } } public override Control DataControl { get { return CheckBoxList1; } }
      
      







変更後、Dynamic Dataは何も起こらなかったかのように機能し続け、開発プロセスを引き続き楽しむことができます。






ソース



以下は、記事のトピックに関するリンクのリストです。 それらが役に立つことを願っています。






All Articles