ADO.NET Entity Framework学习笔记(2)建模[转]
模型結構
?
[概念模型]中要有[實體鍵], [實體鍵]要與表中的 [主鍵] 對應,也就是說表必須要有主鍵.
表中的[唯一鍵]不會在[概念模型]中體現
在[概念模型]中默認是不允許修改[實體鍵]的值的
聯合主健可以正常映射
如果為屬性賦值超過字段長度保存時,會向數據庫提交,數據庫會返回錯誤
聯合主健的主外關系可以正常映射
只有基于主健的主外關系可以在模型向導中自動建立
| Conceptual Model | 概念模型 用于描述實體(Entity)類型及其關系 | |
| Storage Model | 存儲模型 用于描述數據庫實際存儲架構 | |
| Mapping Specification | 映射規范 將概念模型和存儲模型連接起來,以便進行操作轉換 | |
| Entity Class | 實體類 用于描述實體的屬性,每一個實體類都會定義一個屬性或多個屬性為一個鍵屬性(Key Properties),用于唯一標識一個實體 實體類型可以通過繼承關系加以擴展 | |
| Entity Set | 實體集 實體(Entity)存在于實體集(Entity Set)中,就像表格中的行存在于表格中的一樣 | |
| Entity Containe | 實體容器, 實體集定義在實體容器(Entity Container)中 | |
| 關聯 | 關聯 定義了實體之間的關系,可以直接通過關聯,來訪問相關聯的對象,關聯分為一對一、一對多、多對多 關聯通過Association Type來定義,過實體類中的Navigation屬性就可以訪問與實體相關聯的實體 | |
?
模型關系說明
?
?
模型設計器結構說明
?
?
?
?
?
EDM
?
EF 沒有采取 LINQ to SQL 基于Attribute映射的做法。
為了適應變化和提供更多的數據庫類型擴展,EF 提供了專門的定義語言來完成模型設置
| Conceptual schema definition language (.csdl) | ? |
| Store schema definition language (.ssdl) | ? |
| Mapping specification language (.msl) | ? |
?
默認,Model設計器將(.csdl)(.ssdl)(.msl)存放在一個名為(.edmx)的XML 格式定義文件,并會根據設計自動生成對應的Context與實體類
?
Model設計器
| 數據庫中的表 | |
| 模型 | |
| 模型生成選項 |
?
?
edmx文件
| ? | <?xml version="1.0" encoding="utf-8"?> <edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx"> <!-- EF Runtime content --> |
| ? | <edmx:Runtime> |
| 存儲模型 | <!-- SSDL content --> <edmx:StorageModels> <Schema Namespace="myModel.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2008" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2006/04/edm/ssdl"> <EntityContainer Name="myModelStoreContainer"> <EntitySet Name="myTab" EntityType="myModel.Store.myTab" store:Type="Tables" Schema="dbo" /> </EntityContainer> <EntityType Name="myTab"> <Key> <PropertyRef Name="a" /> </Key> <Property Name="a" Type="nchar" Nullable="false" MaxLength="10" /> <Property Name="b" Type="nchar" Nullable="false" MaxLength="10" /> <Property Name="c" Type="nchar" MaxLength="10" /> <Property Name="d" Type="nchar" MaxLength="10" /> </EntityType> </Schema> </edmx:StorageModels> |
| 概念模型 | <!-- CSDL content --> <edmx:ConceptualModels> <Schema Namespace="myModel" Alias="Self" xmlns="http://schemas.microsoft.com/ado/2006/04/edm"> <EntityContainer Name="mySets"> <EntitySet Name="myTab" EntityType="myModel.myTab" /> </EntityContainer> <EntityType Name="myTab"> <Key> <PropertyRef Name="aa" /> </Key> <Property Name="aa" Type="String" Nullable="false" MaxLength="10" Unicode="true" FixedLength="true" /> <Property Name="bb" Type="String" Nullable="false" MaxLength="10" Unicode="true" FixedLength="true" /> <Property Name="cc" Type="String" MaxLength="10" Unicode="true" FixedLength="true" /> <Property Name="dd" Type="String" MaxLength="10" Unicode="true" FixedLength="true" /> ? </EntityType> </Schema> </edmx:ConceptualModels> |
| 映射 | <!-- C-S mapping content --> <edmx:Mappings> <Mapping Space="C-S" xmlns="urn:schemas-microsoft-com:windows:storage:mapping:CS"> <EntityContainerMapping StorageEntityContainer="myModelStoreContainer" CdmEntityContainer="mySets"> <EntitySetMapping Name="myTab"> <EntityTypeMapping TypeName="IsTypeOf(myModel.myTab)"> <MappingFragment StoreEntitySet="myTab"> <ScalarProperty Name="aa" ColumnName="a" /> <ScalarProperty Name="bb" ColumnName="b" /> <ScalarProperty Name="cc" ColumnName="d" /> <ScalarProperty Name="dd" ColumnName="c" /> </MappingFragment> </EntityTypeMapping> </EntitySetMapping> </EntityContainerMapping> </Mapping> </edmx:Mappings> |
| ? | </edmx:Runtime> |
| 圖形設計器的配置部份 | <!-- EF Designer content (DO NOT EDIT MANUALLY BELOW HERE) --> <edmx:Designer xmlns="http://schemas.microsoft.com/ado/2007/06/edmx"> <edmx:Connection> <DesignerInfoPropertySet> <DesignerProperty Name="MetadataArtifactProcessing" Value="EmbedInOutputAssembly" /> </DesignerInfoPropertySet> </edmx:Connection> <edmx:Options> <DesignerInfoPropertySet> <DesignerProperty Name="ValidateOnBuild" Value="true" /> </DesignerInfoPropertySet> </edmx:Options> <!-- Diagram content (shape and connector positions) --> <edmx:Diagrams> <Diagram Name="myModel"> <EntityTypeShape EntityType="myModel.myTab" Width="1.5" PointX="0.75" PointY="0.75" Height="1.7" IsExpanded="true" /> </Diagram> </edmx:Diagrams> </edmx:Designer> |
| ? | </edmx:Edmx> |
?
Context
| public class myContext :ObjectContext { ? public myContext(EntityConnection connection) : base(connection, "mySets") { ? } ? public ObjectQuery<myTab> myTab { get { if ((this._myTab == null)) { this._myTab = base.CreateQuery<myTab>("[myTab]"); } return this._myTab; } } private ObjectQuery<myTab> _myTab; ? ? public void AddTomyTab(myTab myTab) { base.AddObject("myTab", myTab); } } |
?
實體類
| [EdmEntityType(NamespaceName = "myModel", Name = "myTab")] [DataContract(IsReference = true)] [Serializable()] ? public class myTab :EntityObject { ? public static myTab CreatemyTab(string aa, string bb) { myTab myTab = new myTab(); myTab.aa = aa; myTab.bb = bb; return myTab; } ? private string _aa; [EdmScalarProperty(EntityKeyProperty = true, IsNullable = false)] [DataMember()] public string aa { get { return this._aa; } set { this.ReportPropertyChanging("aa"); this._aa = StructuralObject.SetValidValue(value, false); this.ReportPropertyChanged("aa"); } } ? ? ? private string _bb; [EdmScalarPropertyAttribute(IsNullable = false)] [DataMemberAttribute()] public string bb { get { return this._bb; } set { ? this.ReportPropertyChanging("bb"); this._bb = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, false); this.ReportPropertyChanged("bb"); ? } } ? ? // private string _cc; [EdmScalarProperty()] [DataMember()] public string cc { get { return this._cc; } set { this.ReportPropertyChanging("cc"); this._cc =StructuralObject.SetValidValue(value, true); this.ReportPropertyChanged("cc"); } } // private string _dd; [EdmScalarProperty()] [DataMember()] public string dd { get { return this._dd; } set { this.ReportPropertyChanging("dd"); this._dd = StructuralObject.SetValidValue(value, true); this.ReportPropertyChanged("dd"); } } ? } |
?
使用
| myContext cn; ? EntityConnection econ = new EntityConnection(); ? string s = @" metadata=res://*/myModel.csdl |res://*/myModel.ssdl |res://*/myModel.msl ; ? provider=System.Data.SqlClient; ? provider connection string="" Data Source=.; Initial Catalog=LingTestDB; Integrated Security=True; MultipleActiveResultSets=True; "" "; ? econ.ConnectionString = s; ? cn = new myDate.myContext(econ); ? this.dataGridView1.DataSource = cn.myTab; |
?
?
使用向導創建模型
?
?
?
?
?
?
映射基本規則
?
1.[概念模型]的[數據類型],[鍵],[非空]約束要與[存儲模型]對應
?
?
2.[概念模型]的屬性名與[存儲模型]的字段名不必一致
?
3.[存儲模型]的字段如果有[鍵],[非空]約束, [概念模型]必需要有對應的屬性與之映射
?
4. [概念模型]中出現的屬性,在[存儲模型]中必須要有對應的字段映射
5. [存儲模型]的多個字段可以映射到[概念模型]的同一個屬性上
加載時, [概念模型]的屬性加載[存儲模型]的第一個字段值
保存時, [概念模型]的屬性會保存到[存儲模型]的多個字段上
?
映射條件
?
?
?
?
繼承
1. 要實現繼承,要使用映射條件進行篩選
2. [概念模型]與 [子概念模型] 所有的篩選條件不能有相的
3. [子概念模型] 自動得到 [概念模型] 的屬性
4. [子概念模型] 中可以沒有屬性
5. 所的[子概念模型] 的篩選條件將以[Or]的方式影響[概念模型]的篩選,也就是說[概念模型]的記錄將包括[子概念模型] 記錄
6. [概念模型]與 [子概念模型] 共用同一個 [實體集], [實體集]的數據類型為 ObjectQuery<概念模型>
7. 可以使用類型轉換的方式從[實體集]得[子概念模型]的數據
?
| myContext context = new myContext(); ObjectQuery<myTab> a = context.myTabSets; ObjectQuery<myTabEx1> b = context.myTabSets.OfType<myTabEx1>(); ObjectQuery<myTabEx2> c = context.myTabSets.OfType<myTabEx2>(); |
?
?
?
?
多表聯合
?
1. 不要求在數據庫中有關系,最好是主鍵對主鍵
2. 使用對聯的方式,只篩選出有對應鍵的記錄
3. 插入時,會在兩個表中同時插入鍵相同的記錄
4. 刪除時,會同時在兩個表中刪除鍵相同的記錄
?
?
關聯
?
[(1)—(*)] 關聯
?
1. [(1)—(*)]為主外關系,主鍵表為(1),外鍵表為(*)
2. 外鍵字段不能出現在[概念模型]中
3. 可以在向導中直接跟據數據庫中的關系直接生成,也可以在設計[概念模型]時任意添加
4. 關聯要綁定到外鍵表上
5. 要刪除主鍵時,要保證內存中沒有對應的外鍵數據
6. 插入外鍵數據,可以插入到主鍵的外鍵集合,也可創建帶主鍵信息的外鍵對象后直接插入到Context中
表
設置
?
?
?
?
操作數據
| 從主鍵表訪問數據 | myContext context = new myContext(); ? ObjectQuery<tab1> tab1_List = context.tab1; ? ? foreach (tab1 tab1_Entity in tab1_List) { ? Console.WriteLine("{0},{1}", tab1_Entity.a, tab1_Entity.b); ? EntityCollection<tab2> tab2_List = tab1_Entity.Nvtab2; ? tab2_List.Load(); //加載外鍵數據 ? foreach (tab2 tab2_Entity in tab2_List) { Console.WriteLine("{0},{1},{2}", tab2_Entity.ID,tab2_Entity.x,tab2_Entity.y); } } |
| lzm ,456 3 ,5 ,6 4 ,7 ,8 wxd ,123 1 ,1 ,2 2 ,3 ,4 | |
| 從外鍵表訪問數據 | myContext context = new myContext(); ObjectQuery<tab2> tab2_List = context.tab2; ? foreach (tab2 tab2_Entity in tab2_List) { Console.WriteLine("{0},{1},{2}", tab2_Entity.ID, tab2_Entity.x, tab2_Entity.y); ? tab2_Entity.NVtab1Reference.Load(); //加載主鍵數據 ? tab1 tab1 = tab2_Entity.NVtab1; ? Console.WriteLine("{0},{1}", tab1.a, tab1.b); } |
| 1 ,1 ,2 wxd ,123 2 ,3 ,4 wxd ,123 3 ,5 ,6 lzm ,456 4 ,7 ,8 lzm ,456 | |
| 刪除主鍵 | myContext context = new myContext(); var v = context.tab1.First(p => p.a == "wxd"); ? // 要刪除主鍵時,要保證內存中對應的外鍵數據為空 ? //v.Nvtab2.Load(); //if (v.Nvtab2.Count != 0) //{ // List<tab2> list = new List<tab2>(); // foreach (var w in v.Nvtab2) // { // list.Add(w); // } // foreach (var ww in list) // { ? // context.DeleteObject(ww); // } //} ? context.DeleteObject(v); ? context.SaveChanges(); |
| 直接插入外鍵數據 | myContext context = new myContext(); tab2 tab2 = new tab2(); ? tab2.ID = "101"; tab2.x = "555"; tab2.y = "666"; ? tab2.Nvtab1 = context.tab1.First(p => p.a == "wxd"); //要有主鍵信息 ? context.AddTotab2(tab2); ? context.SaveChanges(); |
| 通過主鍵插入外鍵數據 | myContext context = new myContext(); ? var tab1 = context.tab1.First(p => p.a == "wxd"); ? //第1條外鍵記錄 tab2 r1 = new tab2(); r1.ID = "103"; r1.x = "r1"; r1.y = "r1"; tab1.Nvtab2.Add(r1); ? //第2條外鍵記錄 tab2 r2 = new tab2(); r2.ID = "104"; r2.x = "r1"; r2.y = "r1"; tab1.Nvtab2.Add(r2); ? context.SaveChanges(); |
?
[(1)—(1)]關聯
1. [(1)—(1)]為主主關系,既兩個表的主鍵關聯
2. 兩個表的地位是平等的
3. 主鍵字段不能刪除
4. 可以在向導中直接跟據數據庫中的關系直接生成,也可以在設計[概念模型]時任意添加
5. 關聯可綁定到任意一個表上
6. 刪除時,要先將關聯數據刪除
7. 插入時,要有與之關聯的數據
表
?
設置
?
操作數據
| 讀取 | myContext context = new myContext(); ? ObjectQuery<tab1> tab1_List = context.tab1; ? ? foreach (tab1 tab1_Entity in tab1_List) { ? Console.WriteLine("{0},{1}", tab1_Entity.a, tab1_Entity.b); ? tab1_Entity.NVtab3Reference.Load(); //加載關聯數據 ? tab3 tab3 = tab1_Entity.NVtab3; ? ? ? Console.WriteLine("{0},{1},{2}", tab3.a, tab3.m, tab3.n); ? } |
| lzm ,456 lzm ,mmmm ,nnnn wxd ,123 wxd ,nnn ,nnn | |
| myContext context = new myContext(); ? ObjectQuery<tab3> tab3_List = context.tab3; ? ? foreach (tab3 tab3_Entity in tab3_List) { ? Console.WriteLine("{0},{1},{2}", tab3_Entity.a, tab3_Entity.m,tab3_Entity.n ); ? tab3_Entity.NVtab1Reference.Load(); //加載關聯數據 ? tab1 tab1 = tab3_Entity.NVtab1; ? ? ? Console.WriteLine("{0},{1}", tab1.a, tab1.b ); ? } | |
| lzm ,mmmm ,nnnn lzm ,456 wxd ,nnn ,nnn wxd ,123 | |
| 刪除 | myContext context = new myContext(); ? var tab3 = context.tab3.First(p => p.a == "wxd"); ? //-要按順序 ? tab3.NVtab1Reference.Load(); // 加載關聯數據 ? context.DeleteObject(tab3.NVtab1); //刪除關聯數據 ? context.DeleteObject(tab3); // 刪除 ? // context.SaveChanges(); |
| 插入 | myContext context = new myContext(); ? tab1 tab1 = new tab1(); tab1.a = "wxwinter"; tab1.b = "789"; ? //關聯 tab1.NVtab3 = new tab3(); tab1.NVtab3.a = "wxwinter"; tab1.NVtab3.m = "mm"; tab1.NVtab3.n = "mm"; ? context.AddTotab1(tab1); ? context.SaveChanges(); |
?
[(1)—(0..1)]關聯
設計與[(1)—(0..1)]相同.
?
1. 插入(1)時,可以不插入(0..1)
2. 刪除(0..1) 時,可以不刪除(1)
3. 插入(0..1)時,需要插入(1)
4. 刪除(1) 時, 需要刪除(0..1)
?
?
?
?
[(*)—(*)]關聯
表
?
?
顯示中轉方式
?
隱示中轉方式
1. 要實現這個關聯,要將關聯綁定到 [中轉表(安排表)]上
2. 所用的[中轉表(安排表)]不能以[概念模型]的方式出現
3. 兩個表的地位是平等的
4. 添加一端的(*)時,不受另一端(*)約束
5. 可以在添加一端的(*)時,通過[關聯集合]將數據也添加到[關聯表]與[中轉表]中
6. 如果加載關聯數據,[中轉表]中的關聯數據也會被刪除.
如果不加載關聯數據,將不會刪除[中轉表]中的關聯數據
?
?
?
操作數據
| 得到數據 | myContext context = new myContext(); ? ObjectQuery<部門表> bList = context.部門表; ? foreach (部門表 b in bList) { Console.WriteLine("{0},{1}", b.部門, b.部門說明); ? b.場地表.Load(); ? EntityCollection<場地表> cList = b.場地表; ? foreach (場地表 c in cList) { Console.WriteLine("{0},{1}", c.場地, c.場地說明); } } |
| 丙 ,1 a ,11 b ,22 c ,33 甲 ,2 a ,11 乙 ,3 a ,11 b ,22 | |
| myContext context = new myContext(); ? ObjectQuery<場地表> cList = context.場地表; ? foreach (場地表 c in cList) { Console.WriteLine("{0},{1}", c.場地, c.場地說明); ? c.部門表.Load(); ? EntityCollection<部門表> bList = c.部門表; ? foreach (部門表 b in bList) { Console.WriteLine("{0},{1}", b.部門, b.部門說明); } } | |
| a ,11 丙 ,1 甲 ,2 乙 ,3 b ,22 丙 ,1 乙 ,3 c ,33 丙 ,1 | |
| 刪除數據 | myContext context = new myContext(); ? 場地表 c = context.場地表.First(p => p.場地 == "a"); ? ? //1.如果加載關聯數據,[中轉表]中的關聯數據也會被刪除, //2.如果不加載關聯數據,將不會刪除[中轉表]中的關聯數據 ? //c.部門表.Load(); // <-------[是/否] ? ? context.DeleteObject(c); context.SaveChanges(); |
| 添加數據 | myContext context = new myContext(); ? 場地表 c = new 場地表(); c.場地 = "d"; c.場地說明 = "44"; context.AddTo場地表(c); context.SaveChanges(); |
| 同時添加數據到 [源表], [關聯表], [中轉表] | //可以將數據同時添加[源表],[關聯表],[中轉表] myContext context = new myContext(); ? 場地表 c = new 場地表(); c.場地 = "e"; c.場地說明 = "55"; c.部門表.Add(new 部門表() { 部門 = "vv", 部門說明 = "vv" }); context.AddTo場地表(c); context.SaveChanges(); |
?
?
映射存儲過程與函數
?
返回表型存儲過程
存儲過程
| 查詢 PRSelectDBItem | CREATE PROCEDURE PRSelectDBItem @v nvarchar(50) ? as select * from DBItem where ItemID=@v |
?
使用向導生成映射
| myContext context = new myContext(); ? ObjectResult<DBItem> dbitemList= context.PRSelectDBITem("a"); ? foreach (var r in dbitemList) { Console.WriteLine("{0},{1}", r.ItemID, r.ItemMatter); } |
?
代碼實現
| public class Context :ObjectContext { public Context() : base("name=myContext", "myContext") { } public ObjectResult<DBItem> PRSelectDBITem(string v) { return base.ExecuteFunction<DBItem>("PRSelectDBITem", new ObjectParameter("v", v)); } } |
| Context context = new Context(); ? ObjectResult<DBItem> dbitemList = context.PRSelectDBITem("a"); ? foreach (var r in dbitemList) { Console.WriteLine("{0},{1}", r.ItemID, r.ItemMatter); } |
?
?
?
命令型存儲過程
存儲過程
| 插入 PRinsertDBItem | CREATE PROCEDURE PRinsertDBItem @ItemID nvarchar(50), @ItemMatter nvarchar(50) ? as insert into DBItem (ItemID,ItemMatter) values (@ItemID ,@ItemMatter) |
?
使用向導生成映射
?
代碼實現
?
| string econString = @" metadata=res://*/myModel.csdl |res://*/myModel.ssdl |res://*/myModel.msl ; ? provider=System.Data.SqlClient; ? provider connection string="" Data Source=.; Initial Catalog=LingTestDB; Integrated Security=True; MultipleActiveResultSets=True; "" "; ? ? EntityConnection econ = new EntityConnection(); econ.ConnectionString = econString; ? ? ? EntityCommand ecmd = new EntityCommand(); ? ecmd.CommandType = CommandType.Text; ? ecmd.Connection = econ; ? ecmd.CommandText = "myContext.PRinsertDBItem"; ? ecmd.CommandType = CommandType.StoredProcedure; ? ? ? EntityParameter p1 = new EntityParameter("ItemID", System.Data.DbType.String); p1.Value = "aaa"; ? EntityParameter p2 = new EntityParameter("ItemMatter", System.Data.DbType.String); p2.Value = "bbb"; ? ? ecmd.Parameters.Add(p1); ? ecmd.Parameters.Add(p2); ? ? econ.Open(); ? ecmd.ExecuteNonQuery(); |
?
?
參數返回值型存儲過程
存儲過程
?
| 算加法 PRadd | CREATE PROCEDURE PRadd @x int = 0, @y int = 0, @s int = 0 output ? as set @s= @x * @y |
?
使用向導生成映射
?
代碼實現
| string econString = @" metadata=res://*/myModel.csdl |res://*/myModel.ssdl |res://*/myModel.msl ; ? provider=System.Data.SqlClient; ? provider connection string="" Data Source=.; Initial Catalog=LingTestDB; Integrated Security=True; MultipleActiveResultSets=True; "" "; ? ? EntityConnection econ = new EntityConnection(); econ.ConnectionString = econString; ? ? ? EntityCommand ecmd = new EntityCommand(); ? ecmd.CommandType = CommandType.Text; ? ecmd.Connection = econ; ? ecmd.CommandText = "myContext.PRadd"; ? ecmd.CommandType = CommandType.StoredProcedure; ? ? ? EntityParameter p1 = new EntityParameter("x", System.Data.DbType.Int32); p1.Value = 123; ? EntityParameter p2 = new EntityParameter("y", System.Data.DbType.Int32); p2.Value = 456; ? ? EntityParameter rt = new EntityParameter("s", System.Data.DbType.Int32, 0, ParameterDirection.Output, false, 0, 0, "", DataRowVersion.Current, 0); ? ecmd.Parameters.Add(p1); ? ecmd.Parameters.Add(p2); ecmd.Parameters.Add(rt); ? ? econ.Open(); ? ecmd.ExecuteNonQuery(); ? Console.WriteLine(rt.Value); //579 |
轉載于:https://www.cnblogs.com/lingyuan/archive/2010/10/29/1864347.html
總結
以上是生活随笔為你收集整理的ADO.NET Entity Framework学习笔记(2)建模[转]的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 在程序员的道路上,义无反顾的努力,有思想
- 下一篇: WPF 2D绘图(2)Geometry