Description of Entity notes corresponding to the automatic association query and automatic association update navigation properties of Entity Framework, entityframework
I. First, I want to know about the automatic association query of Entity Framework:
Automatic association query of Entity Framework. Three methods are available: Lazy Loading (delayed Loading), Eager Loading (preload), and Explicit Loading (Explicit Loading ), among them, Lazy Loading and Explicit Loading are both delayed Loading.
(Note: Due to the different Entity Framework versions and the Entity constructed in different modes (DB First, Model First, Code First, the methods for automatically associating queries may vary. The sample Code in this article is based on Entity Framework 6.0 and the Entity constructed in Code First mode)
1. Lazy Loading: This is the default situation (default object context object attribute: Configuration. lazyLoadingEnabled = true. If this attribute is set to false, it is invalid. If the object type contains attributes of other object types (POCO class ), when the following conditions are met, the loading of columns can be delayed,
1. The property type must be public and cannot be Sealed;
2. Mark the property as Virtual
Purpose: When you access the navigation attribute, the relevant entities are automatically loaded from the data source. if the object is not in the object context object, each navigation attribute you access will cause a separate query for the data source.
The sample code is as follows:
[Table ("User", Schema = "dbo")] public class User {[Key] [DatabaseGenerated (DatabaseGeneratedOption. identity)] [Display (Name = "User ID")] public int ID {get; set;} [Required] [MinLength (6)] [MaxLength (15)] [Unique ("User", "UserName")] [Display (Name = "UserName")] public string UserName {get; set ;} [Required] [Display (Name = "Password")] public string Password {get; set;} [Required] [Display (Name = "User Type")] public int UserTypeID {get; set;} [ForeignKey ("UserTypeID")] public virtual UserType {get; set;} // when querying a User, userType will be automatically associated with UserTypeID for checking, and the result will be assigned to the UserType attribute}
Ii. Eager Loading: When LazyLoadingEnabled is set to false or the navigation property does not use Virtual, use the IQueryable extension method Include to specify the objects to be attached in advance.
Purpose: The query path in the Include method specifies which objects are returned as part of the initial query. When the Include query path is defined in the query statement, you only need to request the database once, all objects defined in the query path can be returned in a single result set.
The sample code is as follows:
Var entitiesContext = new TEMSContext (); entitiesContext. configuration. lazyLoadingEnabled = false; var users = entitiesContext. users. include ("UserType"); // var users = entitiesContext. set <User> (). include ("UserType"); same as the above statement Assert. areNotEqual (null, users. first (). userType );
Iii. Explicit Loading: Use DbEntityEntry when LazyLoadingEnabled is set to false or the navigation attribute is not Virtual. reference Method to explicitly load a single value of the specified navigation attribute, DbEntityEntry. the Collection method is used to explicitly load the value set of the specified navigation attribute. If DB First is used, ObjectContext can be used. the LoadProperty method is used to explicitly load the specified navigation attribute.
Purpose: The value of the navigation attribute is not queried and loaded from the database during query. You can only use the Reference or Collection method to specify the navigation attribute and call the Load method or ObjectContext. loadProperty is used to query data from the database and assign a value to the specified navigation attribute. If the query result set is large, multiple round-trip queries may occur.
The sample code is as follows:
// This is the explicit loading of Data var entitiesContext = new TEMSContext (); entitiesContext in Code First mode. configuration. lazyLoadingEnabled = false; var user = entitiesContext. users. first (); var u = entitiesContext. entry (user); u. reference (t => t. userType ). load (); Assert. areNotEqual (null, user. userType); // This is the display loading data var DB = new aTestEntities (); db in db First mode. contextOptions. lazyLoadingEnabled = false; var comp = db. companies. first (); db. loadProperty (comp, t => t. parameters); Assert. areNotEqual (0, comp. parameters. count );
Ii. Notes for automatically associating and updating entities corresponding to navigation Properties
If the Lazy Loading (delayed Loading) mode is enabled, that is, when the first associated query condition is met, when the newly added object is executed, Note: If you directly assign a value to the navigation attribute, when submitted to the database, the table records corresponding to the new navigation attribute will be automatically associated, whether or not you have the value of the foreign key attribute corresponding to the specified navigation attribute in the object, the value of the foreign key attribute will be updated after the table record corresponding to the newly added navigation attribute is associated. The expression may be unclear. See the following example:
Var entitiesContext = new TEMSContext (); User user = new User () {UserName = "testuser", RealName = "test account", CompanyID = 1, Company = UserBusiness. currentUser. company}; entitiesContext. users. add (user); entitiesContext. saveChanges ();
In the above Code, CompanyID is the foreign key attribute of the navigation property Company. I have assigned values to both attributes here, and the Company ID is also 1 (there is a record with ID 1 in the Company table ), userBusiness. currentUser is the User currently logged on to our system. It is reasonable to say that after adding a new record, only one record will be added to the User table, in practice, a new record is first added to the Company table (ignore the specified primary key, that is, ID = 1), and assign the returned new ID to CompanyID (for example, 2 ), then a new record is added to the User table to form the User. companyID = 2, not 1. This problem has been plaguing me for several days, and I have not found the root cause. The current solution is to assign only values to the foreign key attribute CompanyID, the navigation property Company is not assigned a value, so that no error will occur during saving. Thank you very much for knowing the reason!
From: zuowj.cnblogs.com