Objective
In this article I'm going to delve into some of the things that are not known in the edmx, and sometimes we need to know some of the storage and mapping principles in the Code first model, and personally think that's necessary and useful, because it's possible that there are some other problems with SQL, and only some of the necessary principles. This will not be overwhelmed when an error is encountered.
Principle
We know that the Entity Data Model (EDM) is a bridge of communication between the application and the data store, and that the interaction between our API and the data store through the attribute mapping is based on edx, so we start with the EDM.
We do not have to rush, we first understand the principle, then through the actual operation you will understand why first understand the principle of the importance of (may be a bit boring, but you take it easy!).
First, give the class for the database table (which is used below):
Public Partial classStudent { Public intKey {Get;Set; } Public stringName {Get;Set; } Public intFlowerid {Get;Set; } Public VirtualFlower Flower {Get;Set; } }
Public Partial classFlower { PublicFlower () { This. Students =NewHashset<student>(); } Public intId {Get;Set; } Public stringRemark {Get;Set; } Public VirtualIcollection<student> Students {Get;Set; } }
Let's take this one step further, and we'll create a new ADO Entity Data Model, as follows:
Because of the code->database that we used before, and now we're going to take the database->code to get the resulting design architecture, we need the EF designer from the database as follows:
After generating the basic schema, we see the most important edmx, the XML file in the EDM, but what we see at this point is the class diagram, which we need to open by specifying an XML tool:
At this point you will see clearly the schema in the EDMX:
The most important of these is the three parts, not to mention that the conceptual model definition language (CSDL) is the conceptual layer, the storage model definition language (SSDL), the storage layer, the mapping language (MSL) between concepts and storage, which is the mapping layer.
Next we'll store the model specifically to see what's in it, and we'll look at a few important parts:
EntityContainer and EntitySet
<EntityContainerName=" dbbyconnectionstringmodelstorecontainer"> <EntitySetName="Flower"Entitytype="Self.flower"Schema="dbo"Store:type="Tables"/> <entityset name="Student"Entitytype="self.student" Schema="dbo"Store:type="Tables"/> <AssociationSetName="Fk_dbo_student_dbo_flower_flowerid"association="Self.fk_dbo_student_dbo_flower_flowerid"> <end role="Flower"entityset="Flower"/> <end role="Student"entityset="Student"/> </AssociationSet> </EntityContainer>
From the above we know: the name of the EntityContainer container is +modelstorecontainer by the database name, and it is the container for EntitySet and AssociationSet , And EntityContainer's role is the important entrance of the query, through exposing entityset, so that we query to EntitySet, and EntitySet is a collection of entities, so through it access to the entity.
EntityType
<entitytype name="Flower"> <Key> <propertyref name="Id"/> </Key> <property name="Id"Type="int"storegeneratedpattern="Identity"nullable="false"/> <property name="Remark"Type="nvarchar (max)"/> </EntityType> <entitytype name="Student"> <Key> <propertyref name="Key"/> </Key> <property name="Key"Type="int"storegeneratedpattern="Identity"nullable="false"/> <property name="Name"Type="nvarchar (max)"/> <property name="Flowerid"Type="int"nullable="false"/> </EntityType>
The entity type is the data type in the model, and we can see that we have the flower and student classes defined in it, and all of its properties are listed under its node.
C-s Mapping
<edmx:Mappings> <mapping space="c-s"xmlns="Http://schemas.microsoft.com/ado/2009/11/mapping/cs"> <entitycontainermappingStorageentitycontainer="Dbbyconnectionstringmodelstorecontainer"Cdmentitycontainer="dbbyconnectionstringentities"> <entitysetmappingName="Flowers"> <EntityTypeMappingTypename="Dbbyconnectionstringmodel.flower"> <mappingfragment storeentityset="Flower"> <scalarproperty name="Id"Columnname="Id"/> <scalarproperty name="Remark"Columnname="Remark"/> </MappingFragment> </EntityTypeMapping> </EntitySetMapping> <entitysetmapping name="Students"> <entitytypemapping typename="dbbyconnectionstringmodel.student"> <mappingfragment storeentityset="Student"> <scalarproperty name="Key"Columnname="Key"/> <scalarproperty name="Name"Columnname="Name"/> <scalarproperty name="Flowerid"Columnname="Flowerid"/> </MappingFragment> </EntityTypeMapping> </EntitySetMapping> </EntityContainerMapping> </Mapping> </edmx:Mappings>
The StorageEntityContainer (Storage entity container) in the above entitycontainermapping corresponds to name in EntityContainer in the storage model, The TypeName in EntityTypeMapping under EntitySetMapping corresponds to the name under EntityType in the conceptual model. That is, by StorageEntityContainer to obtain the EntityContainer in the storage model, and then according to the following EntityType corresponding values to obtain the corresponding entity in the conceptual model, At this point in the mapping layer with TypeName to obtain the entity in the conceptual model, and then start the mapping of one by one, at this time mappingfragment (for the literal meaning of the map fragment), the value named name is mapped to the corresponding column name ColumnName value. This is probably the whole mapping process.
This is my brief introduction, for more details, please refer to the Early EF series that the park friends think twice before translating. Below to enter the actual combat.
Actual combat
Before entering, we should first understand several concepts in the DataSpace enumeration:
- CSpace: The default name for the conceptual model.
- Csspace: The default name of the mapping between the conceptual model and the storage model.
- Ocspace: The default name of the mapping between the object model and the conceptual model.
- Ospace: The default name for the object model.
- Sspace: The default name for the storage model.
In EF we can't get the table name and various properties directly with the DbContext context, but for all of this we can operate through the Metadatawrokspace property in the context ObjectContext. Because this property exposes the GetItems method to make it easy for us to get the data we want.
The question is, what if we want to get the names of all the keys for the entity?
We get all the key names for the entity by adding an extension method Getkeynames to the context, as follows:
Static string[] Getkeynames ( ThisDbContext CTX, Type entity) { varmetadata =((iobjectcontextadapter) CTX). Objectcontext.metadataworkspace; /* Get mappings between CLR type collection and Medata ospace */ varObjitemcollection =(objectitemcollection) metadata. Getitemcollection (dataspace.ospace); / * Gets the entity's metadata as metadata*/by the given CLR type varEntitydata = metadata. getitems<EntityType> (dataspace.ospace). Single (e = Objitemcollection.getclrtype (e) = =entity); / * Returns a collection of all keys for an entity * /returnEntitydata. Keyproperties.select (p =p.name). ToArray (); }
We then call the following to get a collection of all the keys corresponding to that entity
var keynames = ctx. Getkeynames (typeof(Student));
You also understand why you should speak EntityType, EntityContainer and EntitySet through the above. We can't help wondering how a collection of mappings between the CLR types and the storage model should work? Clearly, as follows:
var storeitemcollection = (storeitemcollection) metadata. Getitemcollection (Dataspace.sspace);
We look at the following scenarios where we obtain database tables flower and student by mapping:
The question comes again, how do we get the name of the entity corresponding to the table?
Through the introduction of the above principles, since the table name is definitely at this time the DataSpace enumeration must be the storage model is sspace, and we want to get entityset the corresponding name in the collection, and the table name we know the default is dbo, That is, the value of the schema corresponds to the value of table, and based on this, we try to write the corresponding code:
Static stringGettablename ( ThisDbContext CTX, Type entity) { varmetadata =((iobjectcontextadapter) CTX). Objectcontext.metadataworkspace; varstoreItemCollection =metadata. Getitemcollection (DataSpace. Sspace); varEntitysetbase = storeitemcollection.getitems<EntityContainer> (). Single ().baseentitysets. Where (E = E.name = =entity. Name). Single (); stringTableName = entitysetbase.metadataproperties["Schema"]. Value +"."+ entitysetbase.metadataproperties["Table"]. Value; returnTableName; }
The above code is not explained, the control edmx is very clear, and then we will test to obtain the student table name:
var tableName = ctx. Gettablename (typeof(Student));
The test passes, as follows:
The question comes again, how do we get all the navigation properties of the entity?
Since the navigation property of the entity must be to obtain the entity's premise to get the navigation property, mainly through this metadata. GetItems (dataspace.ospace) to filter out the entity type Finally, a built-in type of Builtintypekind is required. So we give the complete code:
static ienumerable<propertyinfo> getnavigationprpoperties (this DbContext CTX, Type entity) { var metadata = ((iobjectcontextadapter) CTX). Objectcontext.metadataworkspace; var entityType = metadata. GetItems (Dataspace.ospace). Where (d = d.builtintypekind = = Builtintypekind.entitytype ). Oftype<entitytype> (). Where (d = d.name == entity. Name). Single (); return (Entitytype. Navigationproperties . Select (d => entity. GetProperty (D.name)). ToList ()); }
We still make the call and try to get it:
var navigationproperties = ctx. Getnavigationprpoperties (typeof(Student));
The result is successfully taken to the student navigation property flower, as follows:
Summarize
It is also easy to explore the bottom-level of the EDMX ef, the personal feeling of understanding the basic principles to write code and when the code problems to solve will be handy, while understanding these fundamentals for us to build modeling tools on the EF Entity Framework is also very helpful.
EntityFramework's groping EF Bottom (eight)