Entity Framework 6 Recipes Chinese translation series (45), entityframework

Source: Internet
Author: User

Entity Framework 6 Recipes Chinese translation series (45), entityframework

For the original intention of translation and why I chose Entity Framework 6 Recipes, see the beginning of this series.

8-6 get the original object

Problem

  You are using POCO and want to obtain the original object from the database.

Solution

Suppose you have a model from 8 to 7. You are working in an offline environment. Before obtaining client modifications, you want to use the Where clause and FirstDefault () methods to obtain the original object from the database.

Figure 8-7. model containing a single object Item

 

In the code listing 8-9, after obtaining an object, update the object with the new value and save it to the database.

Code List 8-9.Obtain the newly added object and replace its value with the Entry () method.

Class Program {static void Main (string [] args) {RunExample ();} static void RunExample () {int itemId = 0; using (var context = new EFRecipesEntities ()) {var item = new Item {Name = "Xcel Camping Tent", UnitPrice = 99.95 M}; context. items. add (item); context. saveChanges (); // save itemId = item for the next step. itemId; Console. writeLine ("Item: {0}, UnitPrice: {1}", item. name, item. unitPrice. toString ("C");} using (var context = new EFRecipesEntities () {// assume this is an update, the item we get uses a new price var item = new Item {ItemId = itemId, Name = "Xcel Camping Tent", UnitPrice = 129.95 M}; var originalItem = context. items. where (x => x. itemId = itemId ). firstOrDefault <Item> (); context. entry (originalItem ). currentValues. setValues (item); context. saveChanges ();} using (var context = new EFRecipesEntities () {var item = context. items. single (); Console. writeLine ("Item: {0}, UnitPrice: {1}", item. name, item. unitPrice. toString ("C");} Console. writeLine ("Enter input as exit to exit.: "); string line = Console. readLine (); if (line = "exit") {return ;}} public partial class Item {public int ItemId {get; set ;} public string Name {get; set;} public decimal UnitPrice {get; set;} public partial class EFRecipesEntities: DbContext {public EFRecipesEntities (): base ("name = EFRecipesEntities ") {} protected override void OnModelCreating (DbModelBuilder modelBuilder) {throw new UnintentionalCodeFirstException ();} public DbSet <Item> Items {get; set ;}}

The output of the code list is as follows:

Item: Xcel Camping Tent, UnitPrice: $99.95Item: Xcel Camping Tent, UnitPrice: $129.95

Principle

In code listing 8-9, we insert an item into the model and save it to the database. Then we pretend to have received an updated item, maybe to a Silverlight client.

Next, we will update this item to the database. To implement this operation, we get this object from the database to the context. In this process, we use the where clause and FirstOrDefault methods. Then, we use method Entry (), which can access the entire object and can apply many methods on the object. The CureentValues. SetVaules method is used to replace the original value with the new value received from the client. Finally, we call SaveChages to save the object.

 

8-7 manually synchronize object graphs and change trackers

Problem

  You want to manually synchronize your POCO class and change the tracker.

The update tracker accesses the object information that is being tracked by the Entity Framework. The information is not only the values stored in the object attributes, but also the current state of the object, the original values obtained from the database, the attributes modified, and other data. The change tracker provides access to additional operations that can be performed on entities, such as re-loading values from the database to ensure that you have the latest data.

The Entity Framework has two ways to track your objects: Snapshot-based change tracking and change tracking proxy.

Snapshot-based change tracking

The POCO class does not include any. When the attribute value is changed, the logic of the Entity Framework is notified. Because, when the value of an attribute changes, there is no way to notify. When the object framework encounters an object for the first time, it generates a snapshot for the value of each attribute in the memory. When an object is returned from the query, or we add an object to the DbSet, the snapshot is generated. When the Entity Framework needs to know what changes have taken place, it will browse each object and compare it with their current value and snapshot. This process is triggered by a method named DetectChanges in the change tracker.

 

Change tracking agent

Another technology of change tracking is the change tracking agent, which enables the Entity Framework to receive change notifications. The change tracking agent is implemented by dynamically creating a proxy During Delayed loading. This dynamically created proxy not only provides the delayed loading function, but also provides the object when the object changes, it can also notify context objects. To use the change tracking proxy, the class you created must meet the requirements. The entity framework can create a dynamic type derived from your POCO class at runtime. In this type, it reloads each attribute. This dynamic type is called a dynamic proxy, and contains the logic that notifies the Entity Framework when the attribute value changes in the overloaded attribute.

Snapshot-based change tracking relies on the Entity Framework to perform detection when changes occur. The default behavior of DbContext API is to automatically perform detection through events on DbContext. DetectChanges not only updates the context state management information, but also makes changes persistent in the database. When you have a reference type navigation attribute, when the combination of the Set-type navigation attribute and the foreign key, it can also perform link correction. It is important to clearly understand when changes are detected, what they are going to do, and how to control them.

The Entity Framework needs to know that the most obvious change time is during the SaveChanges execution. There are many other places to know about the changes. For example, when querying the current status of the updated object, it needs to scan and detect any changes. Scanning and checking do not only happen in the problems we discuss. When you execute many APIs in DbContext, the run of the DetectChanges method can be caused. In most cases, the DetectChanges method is fast enough to avoid performance problems. However, if there are a large number of objects in the memory or DbContext operations are performed one after another, the self-change detection behavior will become a performance concern. Fortunately, there are options to disable the automatic change detection and manually call it as needed. However, a slight carelessness may lead to unexpected consequences. The Entity Framework provides you with the function of disabling automatic change detection. If you use the DetectChages method with poor performance, you are liable for calling the DetectChages method. Once the code is executed, you must enable it using the DbContext. Configuration. AutoDetectChangesEnable ID.

  

Solution

Suppose you have a model from 8 to 8. It describes the presentation prepared by the presenter for various meetings.

Figure 8-8. Multi-to-Multi-relationship model between the speaker and the prepared speech

In our model, Speaker and Talk are multi-to-many associations. We implement this model through independent association (using the SpeakerTalk chain table in the database), allowing it to support multiple lectures for one speaker and multiple speakers for one speech.

We want to manually synchronize object graphs and change trackers. Call the DetectChanges () method. At the same time, we will demonstrate how synchronization works.

Manually synchronize your POCO object graph and change tracker by using the code listing 8-10.

Code List 8-10.When you need to manually synchronize the change tracker, use the DetectChages () method explicitly.

1 class Program 2 {3 static void Main (string [] args) 4 {5 RunExample (); 6} 7 8 static void RunExample () 9 {10 using (var context = new EFRecipesEntities () 11 {12 context. configuration. autoDetectChangesEnabled = false; 13 var speaker1 = new Speaker {Name = "Karen Stanfield"}; 14 var talk1 = new Talk {Title = "Simulated Annealing in C #"}; 15 speaker1.Talks = new List <Talk> {talk1}; 16 17 // the association is not complete. To 18 Console. writeLine ("talk1.Speaker is null: {0}", 19 talk1.Speakers = null); 20 21 context. speakers. add (speaker1); 22 23 // now the association has been fixed 24 Console. writeLine ("talk1.Speaker is null: {0}", 25 talk1.Speakers = null); 26 Console. writeLine ("Number of added entries tracked: {0}", 27 context. changeTracker. entries (). where (e => e. state = System. data. entity. entityState. added ). count (); 28 context. saveChanges (); 29 // Modify the talk Title 30 talk1.Title = "AI with C # in 3 Easy Steps"; 31 Console. writeLine ("talk1's state is: {0}", 32 context. entry (talk1 ). state); 33 context. changeTracker. detectChanges (); 34 Console. writeLine ("talk1's state is: {0}", 35 context. entry (talk1 ). state); 36 context. saveChanges (); 37} 38 39 using (var context = new EFRecipesEntities () 40 {41 foreach (var speaker in context. speakers. include ("Talks") 42 {4 3 Console. writeLine ("Speaker: {0}", speaker. name); 44 foreach (var talk in speaker. talks) 45 {46 Console. writeLine ("\ tTalk Title: {0}", talk. title); 47} 48} 49} 50} 51} 52 public partial class Speaker53 {54 public int SpeakerId {get; set;} 55 public string Name {get; set ;} 56 public ICollection <Talk> Talks {get; set;} 57} 58 public partial class Talk59 {60 public int TalkId {get; set;} 61 public String Title {get; set;} 62 public System. dateTime CreateDate {get; set;} 63 public System. dateTime RevisedDate {get; set;} 64 public ICollection <Speaker> Speakers {get; set;} 65} 66 public partial class EFRecipesEntities: DbContext67 {68 public EFRecipesEntities () 69: base ("name = EFRecipesEntities") 70 {71} 72 73 protected override void OnModelCreating (DbModelBuilder modelBuilder) 74 {75 throw New UnintentionalCodeFirstException (); 76} 77 78 public DbSet <Speaker> Speakers {get; set;} 79 public DbSet <Talk> Talks {get; set ;} 80 81 public override int SaveChanges () 82 {83 var changeSet = this. changeTracker. entries (). where (e => e. entity is Talk); 84 if (changeSet! = Null) 85 {86 foreach (var entry in changeSet. where (c => c. state = System. data. entity. entityState. added ). select (a =>. entity as Talk) 87 {88 entry. createDate = DateTime. utcNow; 89 entry. revisedDate = DateTime. utcNow; 90} 91 foreach (var entry in changeSet. where (c => c. state = System. data. entity. entityState. modified ). select (a =>. entity as Talk) 92 {93 entry. revisedDate = DateTime. utcNow; 94} 95} 96 return base. saveChanges (); 97} 98}

The output of code listing 8-10 is as follows:

talk1.Speaker is null: Truetalk1.Speaker is null: FalseNumber of added entries tracked: 2talk1's state is: Unchangedtalk1's state is: ModifiedSpeaker: Karen Stanfield    Talk Title: AI with C# in 3 Easy Steps

Principle

The code in Code List 8-10 is a bit complicated. Let's explain it step by step. First, disable automatic tracing, create the speaker and talk instances, and add the talk to the Talks of the speaker navigation attribute set. At this time, talk is already part of the Talks set of the speaker navigation attributes, but speaker is not part of the Speakers set of the talk navigation attributes. The other side of the Association has not been corrected.

Next, we use the Add method to Add speaker1 to the context. The second line of the output shows that the Speakers set of navigation attributes of the talk is correct. The Entity Framework has corrected the other side of the association. Here, the Entity Framework does two things. The first thing is that it notifies the object state manager that three objects are created, although the final output result is not three, this is because it regards many-to-many associations as an independent relationship rather than a separate entity. Therefore, the output result is 2. These objects are speaker and talk. There are no objects associated with many-to-many associations. This is because the change tracker does not return an independent State. The second thing is that the Entity Framework fixes the navigation attribute Speakers in the talk.

When we call the SaveChages () method, the Entity Framework uses the overloaded version of Savechanges. In this method, we update attributes CreateDate and RevisedDate. Before calling the SaveChanges () method, the Entity Framework calls DetectChanges () to find the change. In code listing 8-10, we override the SaveChages () method.

The DetectChanges () method relies on a snapshot to compare the original value and current value of each attribute of each object. This process can determine the changes in the object graph. For a large object graph, this comparison process may be time-consuming.

  

 

Entity Framework exchange QQ group: 458326058. You are welcome to join us.

Thank you for your continued attention, my blog address: http://www.cnblogs.com/VolcanoCloud/

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.