2010-01-20 57 views
1

模型1 - 此模型位於開發服務器上的數據庫中。 Model #1 http://content.screencast.com/users/Keith.Barrows/folders/Jing/media/bdb2b000-6e60-4af0-a7a1-2bb6b05d8bc1/Model1.pngC# - 實體框架 - 瞭解一些基本知識

Model#2 - 此模型位於Prod服務器的數據庫中,並且每天都通過自動提要進行更新。 alt text http://content.screencast.com/users/Keith.Barrows/folders/Jing/media/4260259f-bce6-43d5-9d2a-017bd9a980d4/Model2.png

我已經寫了什麼應該是一些簡單的代碼來同步我的飼料(模型#2)到我的工作數據庫(模型#1)。請注意,這是原型代碼,模型可能不像應該那樣漂亮。此外,進入鏈接數據模型#1(主要是ClientID)是一個手動過程,這就是爲什麼我寫這個簡單的同步方法。

private void SyncFeeds() 
{ 
    var sourceList = from a in _dbFeed.Auto where a.Active == true select a; 
    foreach (RivWorks.Model.NegotiationAutos.Auto source in sourceList) 
    { 
     var targetList = from a in _dbRiv.Product where a.alternateProductID == source.AutoID select a; 
     if (targetList.Count() > 0) 
     { 
      // UPDATE... 
      try 
      { 
       var product = targetList.First(); 
       product.alternateProductID = source.AutoID; 
       product.isFromFeed = true; 
       product.isDeleted = false; 
       product.SKU = source.StockNumber; 
       _dbRiv.SaveChanges(); 
      } 
      catch (Exception ex) 
      { 
       string m = ex.Message; 
      } 
     } 
     else 
     { 
      // INSERT... 
      try 
      { 
       long clientID = source.Client.ClientID; 
       var companyDetail = (from a in _dbRiv.AutoNegotiationDetails where a.ClientID == clientID select a).First(); 
       var company = companyDetail.Company; 
       switch (companyDetail.FeedSourceTable.ToUpper()) 
       { 
        case "AUTO": 
         var product = new RivWorks.Model.Negotiation.Product(); 
         product.alternateProductID = source.AutoID; 
         product.isFromFeed = true; 
         product.isDeleted = false; 
         product.SKU = source.StockNumber; 
         company.Product.Add(product); 
         break; 
       } 
       _dbRiv.SaveChanges(); 
      } 
      catch (Exception ex) 
      { 
       string m = ex.Message; 
      } 
     } 
    } 
} 

現在的問題:

  1. 在型號#2,對於汽車類結構缺少客戶端ID(見紅色圓圈區域)。現在,我學到的一切,EF創建了一個子類的Client,我應該能夠在子類中找到ClientID。然而,當我運行我的代碼時,source.Client是一個NULL對象。我期待EF不能做什麼?有沒有一種方法來正確填充子類?
  2. 爲什麼EF在父表中隱藏子實體ID(在這種情況下是ClientID)?有什麼方法可以揭露它嗎?
  3. 還有什麼像諺語疼拇指伸出?

TIA

+0

對不起您的損失。 [Linkrot](http://content.screencast.com/users/Keith.Barrows/folders/Jing/media/bdb2b000-6e60-4af0-a7a1-2bb6b05d8bc1/Model1.png)是生活的一部分。對我們的數字化歷史構成巨大威脅。 – 3yanlis1bos 2013-03-07 13:15:17

回答

2

1)你看到一個nullsource.Client的原因是因爲相關對象不加載,直到你要求他們,或者他們正在以其他方式加載到對象上下文。下面將顯式地加載它們:

if (!source.ClientReference.IsLoaded) 
{ 
    source.ClientReference.Load(); 
} 

然而,這是次優的,當你有一個以上的記錄列表,因爲它每Load()電話發送一個數據庫查詢。更好的選擇是對Include()方法在初始查詢,指示ORM加載相關實體您有興趣,所以:

var sourceList = from a in _dbFeed.Auto .Include("Client") where a.Active == true select a; 

另一種第三種方法是使用的東西的調用關係的修復行動,例如,在你的例子中,如果相關的客戶端先前被查詢過,他們仍然會在你的對象上下文中。例如:

var clients = (from a in _dbFeed.Client select a).ToList(); 

的EF然後將「固定式」所謂source.Client關係不會null。很顯然,這只是在你要求所有客戶端進行同步列表時纔會做的事情,因此與您的具體示例無關。

請務必記住,除非您請求對象,否則永遠不會將對象加載到EF中!

2) EF的第一個版本故意不將外鍵字段映射到可觀察的字段或屬性。 This是關於此事的一個很好的概要。在EF4.0中,我知道外鍵會因受歡迎的需求而暴露出來。

3)您可能遇到的一個問題是請求產品或AutoNegotiationContacts可能產生的數據庫查詢的數量。作爲替代方案,請考慮在初始查詢中批量加載它們或使用join加載它們。

對一個'操作'使用對象上下文,然後將其處理掉,而不是跨請求持久化它也被認爲是好的做法。初始化開銷很小,因此每個SychFeeds()更合適一個對象上下文。 ObjectContext實現了IDisposable,所以你可以在using塊中實例化它,並在其中包含方法的內容,以確保提交更改後,所有內容都可以正確清理。

+0

感謝您的反饋。要記住這麼多好的做法並鞏固到位。到目前爲止,我喜歡EF比ADO.NET好得多 - 儘管涉及到學習曲線的成本。但是 - 我**愛**學習! – 2010-01-20 23:33:08

+0

另一個說明:上下文是在整個班級的入口點創建的。該類被實例化,調用一個方法,然後該類被禁用,因爲它是沒有會話狀態的Web服務的一部分。我正在研究如何在這種情況下使用using子句。我在班級的申報區域申報我的背景。每個Web服務方法實例化這個類,調用一個方法,然後在退出該方法時清空該類。 (有意義嗎?) – 2010-01-20 23:36:13

+0

如果類的全部目的是針對一種方法,那麼您可以將方法內容包裝在using語句中,例如 私人無效SynchFeed(){ 使用 (YourContext _dbRiv =新YourContext()){ // 做工作 }} 這是假設,因爲我認爲你所說的那樣,上下文(或類)除了SynchFeed()之外什麼都不做。我對使用Web服務並不熟悉,所以如果這不可行,我的道歉。 在這種情況下,這不是什麼大問題 - 當您在多個操作(即對SyncFeed()的很多調用)中保持上下文活動時,您應該真正考慮重構。 – 2010-01-20 23:59:57