<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Entity Framework 4.1 DbContext使用記之三——如何玩轉實體的屬性值?

      之前的兩篇有關EF4.1的文章反響不錯,感謝大家的支持!想體驗EF4.1的新功能?RTW版本已經發布啦http://www.microsoft.com/downloads/en/details.aspx?FamilyID=b41c728e-9b4f-4331-a1a8-537d16c6acdf&displaylang=en   

      Entity Framework 4.1 DbContext使用記之一——如何查找實體? DbSet.Find函數的使用與實現

      Entity Framework 4.1 DbContext使用記之二——如何玩轉本地實體? DbSet.Local屬性的使用與實現

       

      今天的主題是如何玩轉EF4.1中實體的屬性。實體的屬性其實是我們使用EF來訪問和修改實體的關鍵。在EF以前版本中,如果我們一般會直接訪問對象的屬性,比如得到PersonID大于100的所有Person實體的ID和Name:

      using (var context = new MyContext())
      {
          var people 
      = context.People.Where(p => p.PersonID > 100);
          
      for (var p in people)
          {
              Console.WriteLine(
      "ID: {0}, Name:{1}", p.PersonID, p.Name);
          }

      但是如果要得到ObjectContext所track的實體屬性的OriginalValues(原始值)和CurrentValues(當前值),則不是很方便。

       

      而在EF4.1中,由于我們可以使用DbContext.Entry()DbContext.Entry<T>()來得到DbEntityEntryDbEntityEntry<T>對象。通過DbEntityEntry (DbEntityEntry<T>)的OriginalValues和CurrentValues屬性,我們可以方便地得到相應的屬性集合(DbPropertyValues)。通過DbEntityEntry (DbEntityEntry<T>)的Property(Property<T>)方法得到DbPropertyEntryDbPropertyEntry<T>)之后,我們也能通過相應的OriginalValue和CurrentValue屬性得到單個屬性的原始值和當前值。感覺有點繞?看看下面的這些例子應該就簡單明了多了! 

      using (var context = new MyDbContext())
      {
          
      // 有關Find方法,請看EF4.1系列博文一
          var person = context.People.Find(1);

          
      // 得到Person.Name屬性的當前值
          string currentName = context.Entry(person).Property(p => p.Name).CurrentValue;

          
      // 設置Person.Name屬性的當前值
          context.Entry(person).Property(p => p.Name).CurrentValue = "Michael";

          
      // 通過string值"Name"來獲得DbPropertyEntry,而非通過Lambda Expression
          object currentName2 = context.Entry(person).Property("Name").CurrentValue;
      }

       

      再來看看如何得到實體的所有屬性的OriginalValue(原始值),CurrentValue(當前值)和DatabaseValue(數據庫值)吧:

      using (var context = new MyDbContext())
      {
          var person 
      = context.People.Find(1);

          
      // 改變對應的實體的Name屬性
          person.Name = "Michael";

          
      // 改變對應屬性的數據庫值
          context.Database.ExecuteSqlCommand("update Person set Name = 'Lingzhi' where PersonID = 1");

          
      // 輸出對應實體所有屬性的當前值,原始值和數據庫值
          Console.WriteLine("Current values:");
          PrintValues(context.Entry(person).CurrentValues);

          Console.WriteLine(
      "\nOriginal values:");
          PrintValues(context.Entry(person).OriginalValues);

          Console.WriteLine(
      "\nDatabase values:");
          PrintValues(context.Entry(person).GetDatabaseValues());
      }

      這里用到的PrintValues函數實現如下:

      public void PrintValues(DbPropertyValues values)
      {
          
      foreach (var propertyName in values.PropertyNames)
          {
              Console.WriteLine(
      "Property {0} has value {1}",
                                propertyName, values[propertyName]);
          }
      }

      這里具體的輸出大家就當小練習吧,呵呵。

       

      下面再為大家介紹兩個我個人認為比較cool的小功能:

      1) 設置多層的復雜類型的屬性。

      例如,Person實體含有Address復雜類型屬性(Complex - type),Address又含有City這一string類型屬性,那么我們可以這樣來獲得City這一屬性的當前值:

      // 使用Lambda Expression
      string city = context.Entry(person).Property(p => p.Address.City).CurrentValue;

      // 使用string類型的屬性表達
      object city = context.Entry(person).Property("Address.City").CurrentValue;

      這里層次的次數其實沒有限制,可以一直點下去的。:)   EF的內部實現也是使用遞歸調用的方式,之后會有詳細的介紹。 

       

      2) 克隆含有實體屬性當期值,原始值或數據庫值的對象。

      我們可以使用DbPropertyValues.ToObject()方法來克隆將DbPropertyValues中相應的屬性和值變成對象。

      using (var context = new MyDbContext())
      {
          var person 
      = context.People.Find(1);
          var clonedPerson 
      = context.Entry(person).GetDatabaseValues().ToObject();

      這里克隆到的對象不是實體類,也不被DbContext所跟蹤。但這樣的對象在處理數據庫并發等問題時會很有用。


      又到了探尋以上介紹的功能的內部實現的時候啦!我們還是照例使用.NET Reflector來查看EntityFramework.dll。 大家可以打開Reflector和我一起來做個簡單的分析。


      首先是從DbContext.Entry方法得到DbEntityEntry。Entry方法通過調用DbEntityEntry internal的構造函數DbEntityEntry(InternalEntityEntry internalEntityEntry)來創建一個DbEntityEntry對象。這里的InternalEntityEntry又是通過DbContext.InternalContext和先前傳入Entry函數的實體對象來生成的。

      public InternalEntityEntry(InternalContext internalContext, object entity)
      {
          
      this._internalContext = internalContext;
          
      this._entity = entity;
          
          // ObjectContextTypeCache應該是EF內部保存的靜態的類型緩存,用于查找實體類型
          this._entityType = ObjectContextTypeCache.GetObjectType(this._entity.GetType());
          
          // InternalContext.GetStateEntry內部則調用了ObjectStateManager.TryGetObjectStateEntry方法
          this._stateEntry = this._internalContext.GetStateEntry(entity);
          
      if (this._stateEntry == null)
          {
              
      this._internalContext.Set(this._entityType).InternalSet.Initialize();
          }
      }

       

      下面來看看DbEntityEntry.CurrentValues/OriginalValues。CurrentValues和OriginalValues屬性都是DbPropertyValues類型的。DbPropertyValues可以被理解為對于一個實體或復雜類型所有屬性信息的集合。我們通過PropertyNames屬性拿到其所有屬性的名字,通過GetValue或SetValues方法得到或設置屬性值。還能通過我們之前討論的ToObject方法來克隆一個有用與對應實體或復雜類型對象一樣屬性值的對象。演示一下如何使用DbPropertyValues.SetValuesF方法:

      using (var context = new MyDbContext())
      {
          var person 
      = context.People.Find(1);
          var person1 
      = new Person { PersonID = 1, Name = "Michael" };
          var person2 
      = new Person { PersonID = 1, Name = "Lingzhi" };

          var entry 
      = context.Entry(person);
          
          
      // 這里直接將擁有相應屬性值的實體對象直接賦給SetValues方法,直接對person實體的CurrentValues和OriginalValues進行賦值
          entry.CurrentValues.SetValues(person1);
          entry.OriginalValues.SetValues(person2);
      }

       

      這里SetValues內部首先調用了DbHelpers.GetPropertyGetters方法。DbHelpers是System.Data.Entity.Internal命名空間下Internal的類,包含了許多靜態的輔助方法。這里的GetPropertyGetters顧名思義就是得到屬性Getter方法delegate的集合,內部當然是通過PropertyInfo以及.NET Reflection來完成。有了這個Getter方法delegate的集合,我們就能方便地拿到傳入SetValues方法的對象的所有屬性值了,最后則按照所得到的屬性值來進行賦值。

       

      接著我們再來看看如何從DbEntityEntry.Property得到DbPropertyEntry。我們可以傳遞兩種property的表達方式給DbEntityEntry.Property方法:1) Lambda Expression   2) string類型的property表示。先來說說1),在將Lambda Expression解析為對應property時,EF使用了輔助靜態方法DbHelpers.ParsePropertySelector,ParsePropertySelector又調用了另一靜態輔助方法DbHelpers.TryParsePath。具體算法在這里就不做深入解析,簡單說這個TryParsePath方法就是遞歸地將Lambda Expression所表示的property層層深入地獲取到,例如像這樣的Lambda Expression:person => person.Address.City最后就變為"Address.City"。在解析完畢之后,ParsePropertySelector其實也是將Lambda Expression變成了string類型的property表示。自然,EF此時就調用了第二個接受string類型的property表示的DbEntityEntry.Property重載。DbEntityEntry.Property(string)在經過了一系列其他的內部調用之后,到了System.Data.Entity.Internal.InternalEntityEntry.Property(...):

      private InternalPropertyEntry Property(InternalPropertyEntry parentProperty, string propertyName, IList<string> properties, Type requestedType, bool requireComplex)
      {
          
      bool flag = properties.Count > 1;
          Type type 
      = flag ? typeof(object) : requestedType;
          Type declaringType 
      = (parentProperty != null? parentProperty.EntryMetadata.ElementType : this.EntityType;
          PropertyEntryMetadata metadata 
      = this.ValidateAndGetPropertyMetadata(properties[0], declaringType, type);
          
      if ((metadata == null|| ((flag || requireComplex) && !metadata.IsComplex))
          {
              
      if (flag)
              {
                  
      throw Error.DbEntityEntry_DottedPartNotComplex(properties[0], propertyName, declaringType.Name);
              }
              
      throw (requireComplex ? Error.DbEntityEntry_NotAComplexProperty(properties[0], declaringType.Name) : Error.DbEntityEntry_NotAScalarProperty(properties[0], declaringType.Name));
          }
          InternalPropertyEntry entry 
      = (InternalPropertyEntry) metadata.CreateMemberEntry(this, parentProperty);
          
      if (!flag)
          {
              
      return entry;
          }
          
      return this.Property(entry, propertyName, properties.Skip<string>(1).ToList<string>(), requestedType, requireComplex);

      從標黃的語句中不難發現,這個函數也是遞歸調用,并且將多層的property一一解析。 System.Data.Entity.Internal.InternalEntityEntry.Property函數返回InternalPropertyEntry類型的對象。這個對象又被返回給DbPropertyEntry.Create方法,Create方法又調用了InternalPropertyEntry.CreateDbMemberEntry:

       

      public override DbMemberEntry<TEntity, TProperty> CreateDbMemberEntry<TEntity, TProperty>() where TEntity: class
      {
          
      if (!this.EntryMetadata.IsComplex)
          {
              
      return new DbPropertyEntry<TEntity, TProperty>(this);
          }
          
      return new DbComplexPropertyEntry<TEntity, TProperty>(this);
      }

       

      這里的邏輯很簡單,將property分成一般的屬性或復雜類型的屬性,分別處理之。分析到這里,大家應該也發現了DbPropertyEntry中大部分信息都保存在其內部的InternalPropertyEntry對象里。這樣的設計在解析EntityFramework.dll時,我們會經常看到。

       

      呼!這篇文章不是一口氣寫完的了,這幾天挺忙的,不過每天添幾筆,可能思路有些混亂,大家見諒,哈哈!還是那句話,希望對您學習EF有點幫助吧!

       

      PS1:這里為大家帶來一個好消息:微軟一站式實例代碼庫(Microsoft All-In-One Code Framework)即日起正式遷移至MSDN代碼庫了,新的平臺會幫您更輕松地解決開發難題、節省更多時間、獲得更友好的用戶體驗。本人作為這個項目的元老,見到我們已擁有600多個經典的代碼實例,甚感欣慰啊!  更詳細信息,請看http://msdn.microsoft.com/zh-cn/hh124104.aspx?ocid=ban-f-cn-loc-OC201104-MSDN

      之后我將盡力為大家帶來更多有關EF的代碼實例以及相關的介紹!



      PS2:同事開發了一個很cool的MSDN論壇桌面小工具,絕對給力!歡迎使用!(我也出了不少力啊


      也歡迎到MSDN中文論壇ADO.NET與LINQ論壇來提問EF的問題啊,可以試試直接報我的名字Michael Sun,哈哈!

       

      如需轉發請注明原文出處,謝謝: http://www.rzrgm.cn/LingzhiSun/archive/2011/04/13/EF41_WokingWithProperties.html

      posted @ 2011-04-13 09:32  LingzhiSun  閱讀(26454)  評論(44)    收藏  舉報
      主站蜘蛛池模板: 无码AV动漫精品一区二区免费| 国产一区二区不卡自拍| 国产精品青青青高清在线| 国产午夜福利视频合集| 亚洲精品一区二区三区中文字幕 | 久久国产精品伊人青青草| 日韩人妻少妇一区二区三区| 日韩中文字幕综合第二页| 最新国产精品中文字幕| 内射极品少妇xxxxxhd| 国产亚洲精品一区二区无| 大陆精大陆国产国语精品| 国产愉拍精品手机| 亚洲av不卡电影在线网址最新| 99久久久国产精品消防器材| 老太脱裤子让老头玩xxxxx| 日本一区二区三区视频版| 国产成人a在线观看视频免费 | 办公室强奷漂亮少妇同事| 国产成人精品一区二区无| 免费国产午夜理论片不卡 | 在线视频精品中文无码| 风韵丰满妇啪啪区老老熟女杏吧| 一区二区三区四区国产综合| av一本久道久久波多野结衣| 国产做a爱片久久毛片a片| 亚洲 卡通 欧美 制服 中文| 日韩精品中文字幕有码| 人妻少妇88久久中文字幕 | 免费视频成人片在线观看| 天天摸天天碰天天添| 狠狠五月深爱婷婷网| 国产一区二区三区麻豆视频| 日本深夜福利在线观看| 国产好大好硬好爽免费不卡| 视频一区二区三区自拍偷拍| 开心激情站开心激情网六月婷婷| 乱色老熟妇一区二区三区| 精品国产免费一区二区三区香蕉| 日韩高清亚洲日韩精品一区二区 | 鲁一鲁一鲁一鲁一澡|