本文章是由機器翻譯。

資料點

以 JavaScript 免煩惱地存取資料 -- 沒錯,JavaScript

Julie Lerman

下載代碼示例

Julie Lerman
雖然我覺得自己作為一個水管工人軟體發展的時候,我要做的用戶端的發展,以及公平的量。即使在本專欄中,我冒昧進他們相交與資料訪問的用戶端應用程式。但是當用戶端 JavaScript,從來漂亮 — — 我的 JavaScript 技能,不幸的,仍缺乏和每個學習曲線是一個世界的疼痛對我 (和我的 Twitter 追隨者,向我發洩遭受)。但它總是值得當推磚牆上通過,並獲得成功。任何使工作在 JavaScript 中更容易為我是張開雙臂歡迎的東西。所以時,在單頁面應用程式上的 Vermont.NET 使用者組演示文稿,期間病房貝爾從 IdeaBlade,給我們看看開放源碼的資料訪問 API 的 JavaScript,他和他的團隊成立了烹飪,我真的很感興趣。從我與實體框架的角度看,我看到了什麼是經驗的用戶端的 Web 開發使用 EF 相媲美。API 稱為微風,在寫這篇文章的時候是在 Beta 版中。貝爾是他的時間來説明我瞭解更多有關微風為此列與慷慨。你可以在 breezejs.com,那裡還可以找到文檔、 視頻和樣品的令人印象深刻的陣列。

我 2012 年 6 月資料點列中,"資料繫結 OData 中 Web 應用程式與 Knockout.js"(msdn.microsoft.com/magazine/jj133816)、 側重于使用 Knockout.js 來更容易地在用戶端上執行資料繫結。微風無縫地一起挖空,所以我要重溫從 6 月的列的示例。我的目標是要看看如何引進微風可以簡化我的示例工作流中的編碼工作量:

  • 從伺服器獲取資料。
  • 綁定和顯示該資料。
  • 向伺服器回推送更改。

這樣您可以看到如何拼圖塊組合在一起,我就會走過更新的解決方案的關鍵區段。如果您想要按照正確設置解決方案和測試出來的東西,你可以下載完整的解決方案,從 archive.msdn.microsoft.com/mag201212DataPoints

原來的樣本

這裡是解決方案的我早期的關鍵步驟:

  • 在用戶端的定義挖空可用於資料繫結的 person 類:
function PersonViewModel(model) {
  model = model || {};
  var self = this;
  self.FirstName = ko.observable(model.Name || ' ');
  self.LastName = ko.observable(model.Name || ' ');
}
  • 我的資料是通過 OData 資料服務,所以我訪問的資料,使用 datajs,消費從 JavaScript OData 工具組提供。
  • 花了查詢結果 (這作為 JSON 返回),並創建一個 PersonViewModel 實例的值。
  • 我的應用程式然後讓挖空處理還協調使用者所做的更改的資料繫結。
  • 花了修改的 PersonViewModel 實例,並更新其值從我 JSON 物件。
  • 最後,我傳遞給 datajs 將保存回伺服器通過 OData 的 JSON 物件。

我甚至沒打擾的相關資料,因為它會添加更多複雜性的那個小樣本。

使用 ASP.NET Web API 更新的服務

與微風,我可以執行 HTTP 調用到我 OData 服務或服務定義由 ASP.NET Web API (asp。 net/web-api)。 切換到 ASP.NET Web API,我對我以前使用的同一 EF 模型作品的服務 — — 一個加。 我前樣品暴露只有人資料。 因為我知道每個開發者都有一個小集合個人設備的我現在有相關的設備類,表單中的資料。 由我的 ASP.NET Web API 公開的有關職能是 GET,它返回的資料的人 ; 再次獲取設備資料 ; 和單個 POST 為保存更改。 我還使用中繼資料函數來公開我的資料,架構中所示圖 1。 微風將使用此中繼資料,以便了解我的模型。

圖 1 主要成份我 Web API Service 的

readonly EFContextProvider<PersonModelContext> _contextProvider =
  new EFContextProvider<PersonModelContext>();
[AcceptVerbs("GET")]
public IQueryable<Person> People()
{
  return _contextProvider.Context.People;
}
[AcceptVerbs("GET")]
public IQueryable<Device> Devices()
{
  return _contextProvider.Context.Devices;
}
[AcceptVerbs("POST")]
public SaveResult SaveChanges(JObject saveBundle)
{
  return _contextProvider.SaveChanges(saveBundle);
}
[AcceptVerbs("GET")]
public string Metadata()
{
  return _contextProvider.Metadata();
}

在伺服器上的 Breeze.NET

注意到在這些方法中使用的 _coNtextProvider 變數。 我不直接打電話我 EF DbCoNtext (PersonModelCoNtext) 的方法。 相反,我已經讓它裹微風 EFCoNtextProvider。 這是 _coNtextProvider.Metadata 方法從哪裡來,以及 SaveChanges,它接受一個 saveBundle 參數的簽名。 與 saveBundle,微風打算讓我從我的應用程式,它將傳給我 DbCoNtext 堅持到資料庫發送一組資料修改。

我已經命名我的 ASP.NET Web API 應用程式為"BreezyDevices,"所以現在可以要求使用 HTTP://localhost:19428/api/breezydevices/metadata 的架構。 我可以查詢資料通過指定 GET 方法之一:HTTP://localhost:19428/api/breezydevices/people。

因為在用戶端上的微風將查詢保存到 ASP.NET Web API 遠端服務,我可以從我的用戶端應用程式中刪除 datajs。

微風將如何説明我的示例

在此示例的範圍中,我將使用微風來專注于三個痛點:

  1. 我的服務返回並接受裸 JSON,但我需要使用 JavaScript 物件與挖空可觀察到的資料繫結到使用者介面屬性。
  2. 我想要包含相關的資料,但是這是很難在用戶端上。
  3. 我需要將多個更改發送到伺服器進行保存。

與微風,我可以直接向我得到的資料的資料繫結。 我將把配置微風使用挖空,並在回應,它將創建挖空可觀察到的屬性為我蓋下。 這意味著相關資料處理工作是簡單得多,因為不從 JSON 翻譯到可綁定的物件,而且我沒有作出額外的努力,重新界定使用我的查詢結果在用戶端上的圖。

有一些伺服器端配置使用微風所涉及的。 我就會離開微風的文檔有關的詳情的所以我可以專注于該示例的用戶端的資料訪問部分。 因為有更多的微風比什麼我就會被利用在此示例中,一次我給了你們要訪問它的味道和 breezejs.com 要瞭解更多。

圖 2 凡微風適合到工作流伺服器端和用戶端上顯示。

The Breeze.NET API Helps on the Server While the BreezeJS API Helps on the Client
圖 2 Breeze.NET API 説明伺服器上雖然 BreezeJS API 説明在用戶端上

微風從查詢

我的經驗與 OData 和實體框架使查詢與微風熟悉。 我要工作與微風實體管理器的類。 實體管理器能夠讀取由您的服務的中繼資料提供的資料模型和生成 JavaScript"實體"物件本身 ; 你不必定義實體類或寫地圖製作者們。

有位用戶端的配置,以及做。 例如,下面的代碼片斷創建一些微風命名空間的快捷方式,然後配置以使用挖空和 ASP.NET Web API 的微風:

var core = breeze.core,
           entityModel = breeze.entityModel;
core.config.setProperties({
  trackingImplementation: entityModel.entityTracking_ko,
  remoteAccessImplementation: entityModel.remoteAccess_webApi
});

它是可能要配置使用替代綁定框架 (如 Backbone.js 或 JavaScript 的 Windows 庫) 和資料訪問技術 (如 OData) 數量的微風。

下一步,創建實體管理器知道我服務的相對 uri。 實體管理器是實體框架或 OData 上下文相媲美。 它充當我到微風的閘道和緩存的資料:

var  manager = new entityModel.EntityManager('api/breezydevices');

現在我可以定義一個查詢,還有我執行它為我的實體管理器。 此代碼不是使用實體框架和 LINQ 到實體,或使用任何 OData 用戶端 Api,所以這是我最喜歡的部分學習如何使用微風差別太大:

function getAllPersons(peopleArray) {
    var query = new entityModel.EntityQuery()
      .from("People")
      .orderBy("FirstName, LastName");
    return manager
      .executeQuery(query)
      .then(function (data) {
        processResults(data,peopleArray); })
      .fail(queryFailed);
  };

我之所以這麼做在用戶端上並且可以執行我查詢執行非同步,這就是為什麼 executeQuery 方法讓我怎樣做成功執行查詢時定義 (多大歲數) 以及該怎麼做如果失敗 (.fail)。

請注意我把一個陣列 (您很快就會看到這是一個挖空的可觀察到陣列) 到 getAllPersons。 如果查詢執行成功,我將傳遞的 processResults 方法,這將為空陣列,然後將其填充的資料從服務到該陣列。 以前我將不得不逐一查看結果和我自己創建的每個 PersonViewModel 實例。 使用的微風,我可以使用直接返回的資料:

function processResults(data, peopleArray) {
    var persons = data.results;
    peopleArray.removeAll();
    persons.forEach(function (person) {
      peopleArray.push(person);
    });
  }

這給我的人,我將介紹在視圖中的物件的陣列。

GetAllPersons 函數位于物件我叫 dataservice。 我將使用 dataservice 中的代碼的下一位。

Self-Populating 的視圖模型

在我 6 月挖空文章從示例中,查詢和結果是分開的 PersonViewModel 類,我用來在視圖中的資料繫結。 所以我執行了查詢和結果化為與映射代碼,我寫了一個 PersonViewModel 實例。 因為我不需要映射代碼或 PersonViewModel 與微風,我使我的應用程式這一次真的是聰明一點,然後讓它顯示從資料庫中提取的我 dataservice 中的人物件的陣列。 要反映出這一點,我現在有一個名為 PeopleViewModel 的物件。 這暴露了人的屬性,我已作為一個挖空的可觀察到陣列,它我填充使用 dataservice.getAllPersons 定義:

(function (root) {
  var app = root.app;
  var dataservice = app.dataservice;
  var vm = {
    people: ko.observableArray([]),
    }
  };
  dataservice.getAllPersons(vm.people);
  app.peopleViewModel = vm;
}(window));

下載示例中你會發現一個檔稱為 main.js,這是應用程式邏輯的起點。 它包含下面的調用的挖空 applyBindings 方法的程式碼:

ko.applyBindings(app.peopleViewModel, $("content").get(0));

ApplyBindings 方法連接到通過聲明在視圖中的資料繫結的 HTML UI 控制項的視圖模型屬性和方法。

在這種情況下,視圖是 HTML 中我 index.cshtml 一小塊。 請注意將綁定和顯示人民陣列中的第一個和最後一個人的每個物件的名稱的挖空資料繫結標記:

<ul data-bind="foreach: people">
  <li class="person" >
    <label data-bind="text: FirstName"></label>
    <label data-bind="text: LastName"></label>
  </li>
</ul>

當我運行我的應用程式時我得到我的人的資料,唯讀視圖中所示圖 3

Using Breeze and Knockout to Easily Consume Data in JavaScript
圖 3 使用的微風和挖空,很容易使用 JavaScript 中的資料

調整 JavaScript 和挖空以允許編輯

從 6 月的列,您可能還記得,挖空便於將用於編輯資料繫結。 與清風,這是理想的組合輕鬆地編輯資料和它保持回發到伺服器。

第一,我的 dataservice 中物件的調用的微風 manager.saveChanges 方法添加一個函數。 調用時,微風實體管理器捆綁起來的暫止的變更並將其發佈到 Web API 服務:

function saveChanges() {
     manager.saveChanges();
  }

然後我會將新 saveChanges 功能公開為 dataservice 中的一項功能:

var dataservice = {
    getAllPersons: getAllPersons,
    saveChanges: saveChanges,
  };

現在我物件需要公開自己的 PeopleViewModel 保存方法綁定到視圖 ; 視圖模型保存到 dataservice 中 saveChanges 方法的函數委託。 在這裡我使用 JavaScript"匿名函數"來定義保存視圖模型:

var vm = {
    people: ko.observableArray([]),
    save: function () {
      dataservice.saveChanges();
    },
  };

下一步,我替換了輸入元素 (文字方塊) 我標籤以便使用者可以編輯人的物件。 我要從"文本"切換到要啟用雙向綁定到使用者輸入的挖空"價值"關鍵字。 我還與綁定到 PeopleViewModel.save 方法的按一下事件添加圖像:

<img src="../../Images/save.png" 
  data-bind="click: save" title="Save Changes" />
<ul data-bind="foreach: people">
  <li class="person" >
    <form>
      <label>First: </label><input 
        data-bind="value: FirstName" />
      <label>Last: </label> <input 
        data-bind="value: LastName" />
    </form>
  </li>
</ul>

就這樣。 微風和挖空效果會照顧其餘 ! 您可以看到用於編輯中顯示的資料圖 4

Using Breeze to Save Data via JavaScript
圖 4 使用微風保存資料通過 JavaScript

我可以編輯任何或所有這些欄位並按一下保存按鈕。 微風實體管理器將收集的所有資料更改,並將它們推送到伺服器,這反過來會將它們發送到實體框架來更新資料庫。 雖然我不會將擴展此演示,包括插入和刪除操作,微風當然可以處理以及這些修改。

對於大漆面 — — 在中添加相關的資料

這是許多開發人員害怕任何 JavaScript 應用程式的一部分 — — 和它也正是我想寫此列的原因。

我會對我的腳本進行一個小小的改變,將變為可編輯母版每個人表單中添加一個小小的標記 /­細節的人。

我的腳本中更改將在 dataservice 中,凡我將通過在微風中添加,修改查詢查詢方法展開到渴望-­載入每個人的設備,以及該人。 擴大是一個術語,您可能從 OData 或 NHibernate,識別和類似于在實體框架中包括 (微風也有輕鬆地事實後載入相關的資料的支援):

var query = new entityModel.EntityQuery()
           .from("People")
           .expand("Devices")
           .orderBy("FirstName, LastName");

因此,它知道如何顯示裝置的資料,如中所示將然後修改我認為圖 5

圖 5 修改要顯示裝置的資料的視圖

<ul data-bind="foreach: people">
  <li class="person" >
    <form>
      <label>First: </label><input 
        data-bind="value: FirstName" />
      <label>Last: </label> <input 
        data-bind="value: LastName" />
      <br/>
      <label>Devices: </label>
      <ul class="device" data-bind="foreach: Devices">
        <li>
          <input data-bind="value: DeviceName"/>
        </li>
      </ul>                     
    </form>
  </li>
</ul>

至此您已經找到答案。 正如您看到的圖 6,微風處理載入和關係圖的構建在用戶端上的渴望。 它還負責協調要被送回的更新服務的資料。 在伺服器端,微風 EFCoNtextProvider 挑選出的所有更改資料它接收,並可確保實體框架獲取它需要將資料保存到資料庫。

Consuming and Saving Related Data
圖 6 的消費與儲蓄的相關資料

雖然這是簡單-一對多的關係,在寫這篇文章的時候微風的 Beta 版本不支援的多對多關係。

無疼痛的用戶端資料訪問

貝爾告訴我那是他自己的工作專案是 JavaScript 密集型和資料訪問-密集型的靈感微風的痛苦經驗。 他的公司,IdeaBlade,一貫注重創建解決方案,以解決問題的處理斷開連接的資料,和開發者能夠給這個開源專案帶來大量的經驗。 我一直都不願意從事專案上使用了大量的 JavaScript,因為我的技能是瘸腿開頭的而我知道的資料訪問位是否會讓我不高興。 當我看到它,我是很感興趣的微風。 雖然我只抓了抓它的表面,最後一位的什麼我展示你在這篇文章了 — — 多麼輕易地被消耗,並保存相關資料 — — 是什麼真的贏得我了。

Julie Lerman 是 Microsoft MVP,.NET 的導師和顧問住在佛蒙特州的丘陵。您可以找到她提出關於資料訪問和使用者組和會議,世界各地的其他 Microsoft.NET 主題。在她的博客 thedatafarm.com/blog 也是作者的"程式設計實體框架"(2010 年) 以及代碼第一版 (2011 年) 和 DbCoNtext 版 (2012 年),所有從 O'Reilly 媒體。跟著她在 Twitter 上 twitter.com/julielerman

由於以下的技術專家對本文的審閱:病房貝爾