本文章是由機器翻譯。

程式設計師雜談

入門橡樹:資料庫互動

Ted Neward

歡迎回來。我一直走通過入門橡木,動態方法對 Web 開發,同時仍保留了 C# 語言、ASP.NETMVC 框架和你享受的 Microsoft.NET 框架的其餘部分體現在 Ruby 和 Node.js 世界的想法。橡木的實質是"快速回饋、 無摩擦發展和低儀式上,"在專案建立者埃米爾 Rajan 的單詞。

當我離開後時,橡樹被抱怨它不能連接到的資料­基地。在本專欄中,我會教你怎麼進行以下操作:橡木佈線到SQL Server實例、 將另一個相關的類型添加到系統 (評論上的博客條目)、 建立資料庫在橡木、 涉及兩種類型一起使用橡木,和看到橡樹和其生成系統如何處理資料庫交互。

當我們離開我們的英雄......

最後一次橡木當時正在運行,它彈出錯誤訊息和樂於助人的說明性文本,摘錄其中示圖 1。(作為提醒,如果你是在最後一列後 — 在 msdn.microsoft.com/magazine/dn532208 — 你需要關閉伺服器和助手轉輪踢.)我走的更遠之前,請注意如何橡木不是只顯示異常堆疊追蹤和留給我發現或研究什麼可能會引起問題。它實際上試圖診斷問題並提出可能的解決辦法:在這種情況下,"更新 web 配置與您的伺服器實例"。


圖 1 橡木專案説明視窗出現錯誤之後引發。

果然,快速流覽一下 web.config 檔我撿簡單的預留位置是那裡,指向"(本地)"的資料來源,可能會為很多的配置,根據本地的SQL Server實例的配置方式工作的"熱身"創業板示。也就是說,它是,那些微不足道的 LocalDB 在連接字串中刪除,因為它是放在遠端的SQL Server字串 (或 Windows Azure SQL 資料庫中,如果它是可取的在雲計算中保留資料)。我喜歡用 LocalDB,通常是只是一個連接字串的"伺服器 = (localdb) \v11.0;Integrated 安全 = true"探索這樣的因為它是小,很容易清理。無論您使用的 SQL 連接只是將它插入 < 配置 > / < connectionStrings > / < 添加 > 元素,並刷新頁面。事實上,橡樹有一耙 (Ruby 生成工具) 任務為你做這些跨代碼庫:"耙 update_db_server [(localdb) \\v11.0]"(反斜線需要轉義)。

呃......休斯頓嗎?

不幸的是,當再次運行,橡木的行為仿佛一切都沒有改變。並且不幸的是,那是完全真實的。助手不看著更改 web.config 檔中,似乎只有原始程式碼檔。考慮到如何很少更改 web.config 檔,這不是世界末日,但它不會放小抽筋什麼否則是一個非常輕鬆的過程。若要獲取助手承認該專案已經改變,你只需要觸發的一些重要的檔,例如 HomeController.cs 或一些其他原始檔案保存。你可以通過兩種方式:切換到該檔、 在檔中選擇一個隨機的地方、 按下空格鍵和刪除這個空間 (該檔是"髒"和力量保存說服Visual Studio),或只是手動的序幕耙從命令提示符。

一旦這樣做,刷新瀏覽器帶來了不同的錯誤 ("不正確物件名稱 '博客'"),和你正視到世界的資料庫移轉。

資料、 資料、 資料 !

象其概念性的前輩,橡樹想要為你管理資料庫和資料庫架構,因此資料庫可以保持更多或更少"隱藏"從您的視圖。在這種情況下,橡樹不想只是"自動神奇"工藝資料庫從稀薄的空氣,因為你可能會有一些應如何架構的看法 — — 即使你不,資料庫管理員經常做。(誰能贏得這場戰鬥,或誰應該贏得這場戰鬥,是一個討論最好了啤酒 — 最好是很久之後該專案已售出.)

在橡木,做播種資料庫使用一個特定的控制器,SeedController,發現嵌套在 SeedController.cs HomeController 的旁邊。該檔包含一個定義為 SeedController 已經,但是 — 更重要的是為您的目的 — 它還包含一個架構類,這將有助於建立架構和一些示例資料 (可選),放的位置的必要步驟。銘記著,順便說一句,那橡樹的預設約定是多元名稱的資料庫表中的存儲物件,所以博客的物件將存儲在一個名為博客表。圖 2 顯示的架構類。

圖 2 的架構類

public class Schema
{
  // This is the method you'll want to alter
  public IEnumerable<Func<dynamic>> Scripts()
  {
    // Replace all content inside of the Scripts() method with this line
    yield return CreateBlogsTable; // Return just the pointer to the function
  }
  public string CreateBlogsTable() // Here is the function definition
  {
    // This is an example, your table name may be different
    // For more information on schema generation check out the Oak wiki
    return Seed.CreateTable("Blogs",
      Seed.Id(),
      new { Name = "nvarchar(255)" },
      new { Body = "nvarchar(max)" }
    );
  }
  public void SampleEntries()
  {
  }
  public Seed Seed { get; set; }
  public Schema(Seed seed) { Seed = seed; }
}

注意奇怪的"收益回報"的腳本方法中使用。 對於那些你也沒弄明白這在 C# 2.0 中做了什麼,"產量返回"創建的物件的一個匿名的"流"和手回 IEnumerable < T > 指向該流。 在這特定的情況下,它是一個流的功能,並在此特定的方案,它是一個函數 (CreateBlogsTable) 的流。 本質上,您要設置的操作 (Func < 動態 > 流 實例) 代表如何創建資料庫和橡樹將採取每個行動或函數交回從這流並執行它。 這種方式,當有新的更改對架構來發揮作用,這種變化可以在一個新的函數中捕獲 ("CreateComments­表中,"如果你將) 和簡單地添加到清單中。 如果需要,你也可以通過,所以調用第一個函數 Version1,第二個 Version2"版本"的資料庫架構。 橡木維琪已在資料庫移轉的詳細資訊 bit.ly/1bgods5

(對於那些記得我"多模式化.NET"系列,在開始 msdn.microsoft.com/magazine/ff955611,是的這是相當功能面向的方式解決這個問題.)

Seed.Id 函數創建規範的主鍵列:自動遞增的整數值標記為主鍵。 橡木 wiki (bit.ly/1iKfcIb) 包含關於使用種子類到創建資料庫參考這樣做,但總是有做直 SQL,如果所需的特設備用:

public IEnumerable<string> AdHocChange()
{
  var reader = "select * from SampleTable".ExecuteReader();
  while (reader.Read())
  {
    // Do stuff here like yield return strings
  }
    var name = "select top 1 name from sysobjects"
      .ExecuteScalar() as string;
    yield return "drop table SampleTable";
    yield return "drop table AnotherSampleTable";
  }

作為"回報"的另一種方法來調用,添加的 AdHocChange 方法和橡木會愉快地進行,以及這些命令。 (請注意是否你失去對該 wiki 連結的跟蹤,橡樹它的消息中包括錯誤/説明它顯示)。

我不能沒有粘土做磚 !

順便說一句,如果需要一些種子資料的資料庫,這也是 SeedController 的責任的一部分並且再次它下跌到要做到,這次是通過 SampleEntries 方法的架構類。 由於此系統沒有任何真正的種子需要資料,在這裡,我就讓這單獨。

SeedController 編譯後,助手將重新部署專案,但像大多數控制器不會獲取啟動它直到命中與一個 HTTP 要求。 如果你沒超過 SeedController 一眼,看一眼。 它出口四個職位終結點:PurgeDB、 出口,所有和 SampleEntries。 雖然你當然可以自己打終結點,這是最佳左到自動化重複任務的那種 — 在橡木的手段的情況下,犁耙。 果然,"耙子重置"將刪除所有表和重新生成的架構 (它不會發到 /seed/PurgeDB 和/種子 / 所有然後另一個職位),和"耙子樣本"將都刪除表、 重新生成架構和生成示例資料 (郵政 /seed/SampleEntries)。 只是為了保持完整性,順便說一句,是"耙出口"(或郵政 /seed/export) 將返回到使用做那些事情的 SQL 語句。

(捲曲或紅寶石可以從命令列一線行使,順便做一個職位。 Rakefile.rb 檔的示例,說明如何做使用 Net::HTTP::post_from 一職,是很容易剪切並粘貼到另一個別的檔,如果你不想把它埋掉裡面的 Rakefile。 或者你可以用這個作為閘道往學習 Ruby 的藥物。 沒有人判斷)。

它還活著 !

假設有沒有錯別字,耙子重置操作完成後,在瀏覽器中的刷新帶來工作的網頁,(對於博客標題) 的簡單的文字欄位和一個"提交"按鈕。 進入一個新的博客標題將生成一個錯誤,但是 — 雖然博客存在,有種假設 (基於什麼是 Index.cshtml 視圖中) 也是一種與博客相關的東西稱為注釋。

在占主導地位,博客引擎世界簡單的關係模型,博客有評論一對多的關係。 我想要模型,所以首先我需要一種資料類型對於評論的物件,再是簡單的腦死亡,以及,此系統中。 事實上,因為評論是 (類似博客的物件) 基本上是動態物件,不帶任何有趣元素給他們,他們甚至不用模型類定義 — 股票的所有動態物件 (雙子星座類型,為那些在記住我的 2013 年 8 月專欄、"會動態與雙子座圖書館," msdn.microsoft.com/magazine/dn342877) 是精細。

(是的如果你還沒有種"我們是從堪薩斯,托托很長的路"的在現在之前的時刻,這是絕對時間停下來思考:您正在使用業務物件你從來不來定義其類型)。

若要描述關係的博客的評論,但是,有做兩件事。 第一,評論需要一個存儲庫中 (就像博客那樣在我的最後一列):

public class Comments : DynamicRepository
{
}

更重要的是,博客類需要略有革新,以捕獲一對多的關係,既有直接 (博客擁有的注釋物件,在這種情況下意味著作為欄位有一個注釋物件的集合),和間接 (所以橡樹知道 Blog 和發表評論的物件連接到資料庫中,以及如何)。 這通過引入一種新方法,同夥,描述的關係,如中所示圖 3

圖 3 描述的博客和評論的一對多關聯性

public class Blog : DynamicModel
{
  Blogs blogs = new Blogs();
  // Define comments
  Comments comments = new Comments();
  public Blog() { }
  public Blog(object dto) : base(dto) { }
  // Add an Associates method to add the Comments() method
  IEnumerable<dynamic> Associates()
  {
    // And define the association
    // For othere examples of associations check out the Oak wiki
    yield return new HasMany(comments);
  }
}

正如您所看到的它不是真的那麼離譜說你需要做的:該模型很密切匹配一個博客的抽象概念。 這是可以看到的美容和使用動態技術的權力。 這一變化 (同夥方法做"收益回報"的 HasMany) 實際上觸發被添加到博客的三種新方法 — 評論、 CommentIds 和 NewComment — 以支援注釋的關係物件與博客物件,所有這些都是純棚架,通常會要求你寫那些方法"硬道路的"是你使用的正常的、 非動態的 C#。 自然,不過,這一切的工作針對資料庫,您需要備份它帶有資料庫說明的注釋表,這意味著你回來到 SeedController (並隨後耙子重置),作為顯示在圖 4

圖 4 資料庫描述的意見表

public class Schema{
  public IEnumerable<Func<dynamic>> Scripts()
  {
    yield return CreateBlogsTable;
    yield return CreateCommentsTable;
  }
  public string CreateBlogsTable() // Here is the function definition
  {
    return Seed.CreateTable("Blogs",
      Seed.Id(),
      new { Name = "nvarchar(255)" },
      new { Body = "nvarchar(max)" }
    );
  }
  public string CreateCommentsTable() // Here is the function definition
  {
    return Seed.CreateTable("Comments",
      Seed.Id(),
      new { BlogId = "int", ForeignKey = "Blogs(Id)" },
      new { Body = "nvarchar(max)" }
    );
  }
}

因為我在這裡順便說一下,我將添加幾個博客條目,只是為了炫耀如何使用 SampleEntries 方法。 它是比你想像的要容易得多,如中所示圖 5

圖 5 添加博客條目

public void SampleEntries(){
  var blog1 = new // Store the ID
  {
    Name = "Hello, Oak Blog",
    Body = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
  }.InsertInto("Blogs");
  new { Body = "great job!", BlogId = blog1 }.InsertInto("Comments");
  new
  {
    Name = "Here are cat pictures!",
    Body = "Meowem hisum collar sit amet, addipisces lick."
  }.InsertInto("Blogs");
}

再一次動態物件和擴充方法的使用也使其幾乎不看像 C# 了。 (在這種情況下,你不去創造一樣具有自動生成屬性標題和正文,創建匿名物件的一個實例,然後使用擴充方法 InsertInto 做實際插入一個動態物件)。而且,順便說一句,陷阱 blog1 本地變數中的物件的唯一理由是使它可以使用作為博客的 ID 值為對它的評論。

繼續。 刷新與耙示例資料庫,然後刷新瀏覽器。

下一步:使用者輸入的驗證

這將變成一些有趣的東西,如果不是已經。 你沒有模型定義了類型,但您有它的工作模型和資料庫存儲。 (儘管它是公平的建議的架構類中的特設方法重複的使用可以輕鬆地轉到 SQL 腳本) 涉及任何 SQL 腳本,而且很重要的是要指出所有的代碼做的一切都是 (仍然) 藏以原始程式碼形式橡木資料夾中的基架的專案,以防您需要調試或感覺就像流覽。

仍有幾個事情尚未做,如驗證使用者輸入,以確保它可以是存儲之前, 的所有好的和正確但下一次是一個很好的主題。

編碼愉快 !

Ted Neward 是的校長 Neward & 同夥 LLC。他已寫一百多篇和創作和合著十幾本書,其中包括"專業 F # 2.0"(Wrox,2010年)。他是 F # 最有價值球員,並在世界各地的會議上講話。他徵求意見,並定期導師 — 聯繫到他在 ted@tedneward.com 如果你感興趣讓他來與您的團隊一起工作或閱讀他的博客在 blogs.tedneward.com

感謝以下協助校閱本篇文章的技術專家:埃米爾 Rajan (橡木專案建立者)
埃米爾 Rajan 是出現在.Net 岩石、 放牧的代碼和 Hanselminutes 的發展社區的活躍成員。 他在許多具有專門知識。NET 的 Web 框架,其他體系結構中,紅寶石、 JavaScript (前端和 NodeJS),iOS 和 F #。 他是總要爭取更好的通過開放原始碼捐款行業、 獨立諮詢和博客 (amirrajan.net) 和可以在達成 ar@amirrajan.net."