最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Entity?Framework導(dǎo)航屬性介紹

 更新時(shí)間:2022年03月09日 09:26:56   作者:.NET開發(fā)菜鳥  
這篇文章介紹了Entity?Framework的導(dǎo)航屬性,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

一、主鍵和外鍵

關(guān)系型數(shù)據(jù)庫(kù)中的一條記錄中有若干個(gè)屬性,若其中某一個(gè)屬性組是能唯一標(biāo)識(shí)一條記錄,該屬性組就可以稱為主鍵。例如:

學(xué)生版(學(xué)號(hào)、姓名、性別、班級(jí))

其中每個(gè)學(xué)生的學(xué)號(hào)是唯一的,學(xué)號(hào)就是一個(gè)主鍵。

課程表(課程編號(hào),課程名,學(xué)分)

其中課程編號(hào)是唯一的,課程編號(hào)就是一個(gè)主鍵。

成績(jī)表(學(xué)號(hào)、課程號(hào)、成績(jī))

成績(jī)表中單獨(dú)的一個(gè)屬性無(wú)法唯一標(biāo)識(shí)一條記錄,學(xué)號(hào)和課程號(hào)的組合才能唯一標(biāo)識(shí)一條記錄,所以學(xué)號(hào)和課程號(hào)的屬性組是一個(gè)主鍵。

外鍵

成績(jī)表中的學(xué)號(hào)不是成績(jī)表的主鍵,但它和學(xué)生表中的學(xué)號(hào)相對(duì)應(yīng),并且學(xué)生表中的學(xué)號(hào)是學(xué)生表的主鍵,則稱成績(jī)表中的學(xué)號(hào)是學(xué)生表的外鍵。同理:成績(jī)表中的課程號(hào)是課程表的外鍵。

EntityFramework中的導(dǎo)航屬性即外鍵。下面通過(guò)例子講解如何使用EF的導(dǎo)航屬性。

二、導(dǎo)航屬性

1、新建產(chǎn)品分類表,語(yǔ)句如下:

CREATE table Category
(
  CategoryId int primary key not null identity,
  CategoryName varchar(64)
)

新建產(chǎn)品明細(xì)表,其中CategoryId是外鍵

CREATE TABLE [dbo].[ProductDetail](
    [ProductId] [int] IDENTITY(1,1) NOT NULL,
    [ProductName] [varchar](32) NULL,
    [Price] [decimal](9, 2) NULL,
    [CategoryId] [int] NULL,
PRIMARY KEY CLUSTERED
(
    [ProductId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO

ALTER TABLE [dbo].[ProductDetail]  WITH CHECK ADD  CONSTRAINT [FK_Category] FOREIGN KEY([CategoryId])
REFERENCES [dbo].[Category] ([CategoryId])
GO

ALTER TABLE [dbo].[ProductDetail] CHECK CONSTRAINT [FK_Category]
GO

分別往Category表和ProductDetail表中插入一些測(cè)試數(shù)據(jù):

--Category表插入數(shù)據(jù)
INSERT INTO Category (CategoryName)
select '電子產(chǎn)品' union
SELECT '家用電器' UNION
SELECT '圖書'

--ProductDetail表插入數(shù)據(jù)
INSERT INTO ProductDetail (ProductName,Price,CategoryId)
SELECT '蘋果6s手機(jī)',5633,1 UNION
SELECT 'Dell電腦',6998,1 UNION
SELECT '佳能相機(jī)',5633,1 UNION
SELECT '海爾洗衣機(jī)',1234,2 UNION
SELECT '格力空調(diào)',2344,2 UNION
SELECT '美的冰箱',3218,2 UNION
SELECT '白鹿原',342,3 UNION
SELECT 'C#高級(jí)編程(第十版)',145,3 UNION
SELECT '平凡的世界',231,3

2、使用DataBase First模式生成edmx文件,然后查看Category表和ProductDetail表相對(duì)應(yīng)的實(shí)體的定義

Category表定義:

//------------------------------------------------------------------------------
// <auto-generated>
//     此代碼已從模板生成。
//
//     手動(dòng)更改此文件可能導(dǎo)致應(yīng)用程序出現(xiàn)意外的行為。
//     如果重新生成代碼,將覆蓋對(duì)此文件的手動(dòng)更改。
// </auto-generated>
//------------------------------------------------------------------------------

namespace EFNavigateDemo
{
    using System;
    using System.Collections.Generic;

    public partial class Category
    {
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
        public Category()
        {
            this.ProductDetails = new HashSet<ProductDetail>();
        }

        public int CategoryId { get; set; }
        public string CategoryName { get; set; }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection<ProductDetail> ProductDetails { get; set; }
    }
}

Category實(shí)體類中有一個(gè)ProductDetail類型的集合屬性,表示是導(dǎo)航屬性。

實(shí)體類型包含其他實(shí)體類型(POCO類)的屬性(也可稱為導(dǎo)航屬性),且同時(shí)滿足如下條件即可實(shí)現(xiàn)延遲加載:

  • 1.該屬性的類型必須為public且不能為Sealed。
  • 2.屬性標(biāo)記為Virtual。

ProductDetail實(shí)體類定義如下:

//------------------------------------------------------------------------------
// <auto-generated>
//     此代碼已從模板生成。
//
//     手動(dòng)更改此文件可能導(dǎo)致應(yīng)用程序出現(xiàn)意外的行為。
//     如果重新生成代碼,將覆蓋對(duì)此文件的手動(dòng)更改。
// </auto-generated>
//------------------------------------------------------------------------------

namespace EFNavigateDemo
{
    using System;
    using System.Collections.Generic;

    public partial class ProductDetail
    {
        public int ProductId { get; set; }
        public string ProductName { get; set; }
        public Nullable<decimal> Price { get; set; }
        public Nullable<int> CategoryId { get; set; }

        public virtual Category Category { get; set; }
    }
}

ProductDetail類里面有一個(gè)Category類型的屬性。

導(dǎo)航屬性實(shí)現(xiàn)延遲加載的四種方式:

1、方式一

using (var dbContext = new CategoryEntities())
{
        dbContext.Configuration.LazyLoadingEnabled = true; // 默認(rèn)是true,針對(duì)導(dǎo)航屬性
         var categoryList = dbContext.Set<Category>().Where(p => p.CategoryId == 3);
         // 只會(huì)在數(shù)據(jù)庫(kù)里面查詢Category表,不會(huì)查詢ProductDetail表
         foreach(var category in categoryList)
         {
              Console.WriteLine("CategoryId:"+category.CategoryId+ ",CategoryName:"+category.CategoryName);
              // 這時(shí)才會(huì)去數(shù)據(jù)庫(kù)查詢ProductDetail表
              foreach (var product in category.ProductDetails)
              {
                  Console.WriteLine("ProductName:"+product.ProductName);
              }
          }
}

分別在兩處foreach循環(huán)的地方添加斷點(diǎn),然后運(yùn)行程序查看數(shù)據(jù)庫(kù)執(zhí)行的SQL語(yǔ)句情況:

執(zhí)行到斷點(diǎn)1時(shí):

這時(shí)查看數(shù)據(jù)庫(kù)監(jiān)控:

繼續(xù)執(zhí)行到斷點(diǎn)2:

這時(shí)在查看數(shù)據(jù)庫(kù)監(jiān)控:

會(huì)發(fā)現(xiàn)遍歷ProductDetails屬性時(shí)也會(huì)查詢ProductDetail表。

2、方式二

using (var dbContext = new CategoryEntities())
{
      dbContext.Configuration.LazyLoadingEnabled = false; // 不延遲加載,不會(huì)再次查詢了
      var categoryList = dbContext.Set<Category>().Where(p => p.CategoryId == 3);
       // 只會(huì)在數(shù)據(jù)庫(kù)里面查詢Category表,不會(huì)查詢ProductDetail表
       foreach (var category in categoryList)
       {
            Console.WriteLine("CategoryId:" + category.CategoryId + ",CategoryName:" + category.CategoryName);
            // 這時(shí)不會(huì)去數(shù)據(jù)庫(kù)查詢了,所以用戶全是空的
            foreach (var product in category.ProductDetails)
            {
               Console.WriteLine("ProductName:" + product.ProductName);
            }
       }
}

這時(shí)還是采用和上面一樣的方法加入斷點(diǎn),只需要查看第二次循環(huán)時(shí)的數(shù)據(jù)庫(kù)監(jiān)控情況即可:

從上面的截圖中看出,如果LazyLoadingEnabled設(shè)置為false,將不會(huì)再查詢ProductDetail表的數(shù)據(jù)了。

3、方式三

// 顯示加載
using (var dbContext = new CategoryEntities())
{
       // 不延遲加載,指定Include,一次性加載主表和從表的所有數(shù)據(jù)
       var categoryList = dbContext.Set<Category>().Include("ProductDetails").Where(p => p.CategoryId == 3);
       foreach (var category in categoryList)
       {
            Console.WriteLine("CategoryId:" + category.CategoryId + ",CategoryName:" + category.CategoryName);
            // 不會(huì)再查詢
            foreach (var product in category.ProductDetails)
            {
               Console.WriteLine("ProductName:" + product.ProductName);
            }
       }
}

使用Include()方法會(huì)一次性加載所有的數(shù)據(jù):

4、方式四

在上面的方式2中把LazyLoadingEnabled設(shè)置為false以后就不會(huì)再查詢ProductDetail表的數(shù)據(jù)了,這時(shí)如果想要查詢ProductDetail表的數(shù)據(jù)該怎么辦呢?這時(shí)可以使用手動(dòng)加載,代碼如下:

//LoadProperty 手動(dòng)加載
using (var dbContext = new CategoryEntities())
{
      dbContext.Configuration.LazyLoadingEnabled = false; // 不延遲加載,不會(huì)再次查詢了
      var categoryList = dbContext.Set<Category>().Where(p => p.CategoryId == 3);
      foreach (var category in categoryList)
      {
            Console.WriteLine("CategoryId:" + category.CategoryId + ",CategoryName:" + category.CategoryName);
            dbContext.Entry<Category>(category).Collection(p => p.ProductDetails).Load();// 集合顯示加載
             foreach (var product in category.ProductDetails)
             {
                 Console.WriteLine("ProductName:" + product.ProductName);
             }
       }
}

添加斷點(diǎn):

查看數(shù)據(jù)庫(kù)監(jiān)控:

5、插入數(shù)據(jù)

對(duì)于Category和ProductDetail表如何同時(shí)插入數(shù)據(jù)?先看下面的一段代碼:

using (var dbContext = new CategoryEntities())
{
      using (TransactionScope trans = new TransactionScope())
      {
           Category category = new Category()
           {
                CategoryName = "自行車"
           };
           dbContext.Categories.Add(category);
           dbContext.SaveChanges();//category.CategoryId賦值了
           ProductDetail product = new ProductDetail()
           {
                 ProductName = "美利達(dá)",
                 Price = 2312,
                 CategoryId = category.CategoryId
            };

            dbContext.ProductDetails.Add(product);
            dbContext.SaveChanges();
            trans.Complete();//提交事務(wù)
      }
}

在第一次SaveChanges()后面的一行代碼加斷點(diǎn),查看Category信息:

可以看到這是CategoryId已經(jīng)有值了,查詢數(shù)據(jù)庫(kù)ProductDetail表:

這時(shí)Product的信息已經(jīng)插入到數(shù)據(jù)庫(kù)中了,而且CategordId也是上面生成的CategoryId。

但是這樣會(huì)導(dǎo)致一種問題存在:如果第一次SaveChanges()成功,第二次SaveChanges()之前報(bào)錯(cuò)了,但是程序已經(jīng)不能回滾了,這樣就會(huì)導(dǎo)致數(shù)據(jù)不一致了。使用下面的代碼進(jìn)行優(yōu)化:

using (var dbContext = new CategoryEntities())
{
      using (TransactionScope trans = new TransactionScope())
      {
           Category category = new Category()
           {
                CategoryName = "汽車"
           };

           ProductDetail product = new ProductDetail()
           {
                 ProductName = "上海大眾",
                 Price = 190090,
                 CategoryId = category.CategoryId
            };

            category.ProductDetails = new List<ProductDetail>() { product};
            dbContext.Categories.Add(category);
            dbContext.SaveChanges();
            trans.Complete();//提交事務(wù)
       }
}

經(jīng)過(guò)這樣修改以后可以保證數(shù)據(jù)的一致性了。這是情況只適合有導(dǎo)航屬性的。

示例代碼下載地址:點(diǎn)此下載

到此這篇關(guān)于Entity Framework導(dǎo)航屬性的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論

通道| 三门县| 隆昌县| 沾化县| 东乡族自治县| 泽州县| 扶绥县| 佛坪县| 尚志市| 宁都县| 项城市| 九龙县| 黎平县| 民勤县| 平罗县| 聂拉木县| 东城区| 冀州市| 陵川县| 绵阳市| 丰顺县| 祁东县| 樟树市| 莒南县| 上饶市| 静乐县| 邯郸市| 班玛县| 崇信县| 原平市| 洛浦县| 普宁市| 嵊泗县| 大同市| 施秉县| 正阳县| 海城市| 黑水县| 诸城市| 塔城市| 邢台市|