多租戶系統在MVC中具有獨立的數據庫

介紹

隨着寬帶和網絡技術的進步,我們正在看到從傳統的桌面應用轉向基於網絡的系統。雲是這幾天的所有範圍。Sage和Quickbooks等會計軟件包正在被諸如Kashflow和Wave Apps等在線軟件取代。

每個客戶並沒有創建一個獨特的軟件實例,而是像Kashflow和Wave Apps一樣,將他們的系統開發成多租戶應用程序 - 所有用戶都使用該軟件的一個實例。在每種情況下,它們的數據都是通過系統的體系結構與其他客戶的數據分離的。

引用:

多租戶是指軟件架構中的一個原則,其中軟件的單個實例在服務器上運行,爲多個租戶提供服務。租戶是一組用戶在他們使用的軟件上共享相同的觀點。 - 維基百科

這可以通過兩種方式來實現:

單個數據庫 - 創建單個數據庫,所有數據都存儲在此處。每個記錄都分配有一個租戶密鑰,只有屬於該租戶的數據纔可訪問。訪問受應用軟件的限制。

多個數據庫 - 或者,可以使用單獨的數據庫來存儲每個客戶數據。然後可以通過使用SQL登錄憑據來限制對數據庫的訪問。

雖然我多次使用單一數據庫方法,但在開始最近的一個項目時,很明顯多種數據庫方法可能更合適。

多數據庫方法的優點

多數據庫方法的主要優點之一是可以備份和恢復單個用戶的數據。使用單一的數據庫方法,恢復數據庫將消除所有客戶的變化,並且在單個客戶出錯時不可能提供回滾功能。

另外,如果網站變得非常成功,那麼多數據庫系統就可以非常容易地在各個服務器之間移動數據。

然而在我的情況下,主要的賣點是預期一些客戶可能需要定製系統,超出了多租戶設計所能達到的水平。通過使用單獨的數據庫,可以將這些數據庫移動到新的服務器上,並在需要時進行完全自定義。雖然這可能會首先打破多租戶系統的優勢,但它確實提供了單一數據庫系統不能提供的靈活性和麪向未來的優勢。

多數據庫系統的體系結構

多租戶應用程序的體系結構

在多數據庫多租戶系統中,每個用戶數據都存儲在自己的數據庫中。因此需要單獨的數據庫來保存登錄細節,並提供用戶數據存儲位置的詳細信息。這可能指向同一臺服務器上的數據庫或遠程數據位置。

如何使用MVC創建多數據庫系統6

在Visual Studio中,創建一個新的ASP.NET Web應用程序。

創建一個新的項目

選擇MVC作爲模板類型,在“更改認證”中,確保選擇“個人用戶帳戶”。這個例子我們將使用表單認證。

選擇MVC作爲類型

確保選擇個人用戶帳戶

首先,創建一個名爲AccountDAL的文件夾- 我們將使用它來存儲訪問Account數據存儲的所有代碼。

爲帳戶DAL創建一個文件夾

創建一個新類,並將其命名爲DataContext.cs添加下面的代碼:

public class DataContext : DbContext
{
    public DataContext() : base("accountContext")
    {
    }

    public DbSet<Account> Accounts { get; set; }
    public DbSet<User> Users { get; set; }
}

我們將首先使用實體​​框架生成一個DataContext代表存儲在我們Account數據庫中的數據。會有兩個表格:

  • Accounts - 一個帳戶代表一個租戶。這些數據將包含租戶數據存儲的位置。每個帳戶可以有多個用戶。
  • Users - 包含系統所有用戶的登錄用戶名和密碼。每個用戶都綁定到一個帳戶。

將連接字符串添加到web.config以連接到帳戶數據庫:

<connectionStrings>
    <add name="accountContext"

          providerName="System.Data.SqlClient"

          connectionString="Server=desktop\SERVER2012; Database=Accounts;
          Integrated Security=SSPI" />
  </connectionStrings>

而在web.config中,我們也將檢查auth模式是否設置爲表單身份驗證:

<authentication mode="Forms">
    <forms loginUrl="/Account/Login" cookieless="UseCookies" />
</authentication>

接下來,我們創建兩個類來表示數據庫中的表User.csAccount.cs

public class User
{
    public int Id { get; set; }
    public string Email { get; set; }
    public string Password { get; set; }
    public string Name { get; set; }
    public int AccountId { get; set; }
    public virtual Account Account { get; set; }
}

public class Account
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Database { get; set; }
    public virtual ICollection<User> Users { get; set; }
}

我們現在需要創建我們的數據庫。創建一個名爲的新數據庫Accounts,並添加兩個名爲Users 和的Accounts,如下所示:

Accounts

Users

將以下測試數據添加到每個:

最後,讓我們做一些修改我們的LoginLogout功能使用FormsAuthentication

public ActionResult Login(LoginViewModel model, string returnUrl)
{
   if (ModelState.IsValid)
   {
      var dataContext = new AccountDAL.DataContext();
      var user = dataContext.Users.FirstOrDefault
                 (x => x.Email == model.UserName && x.Password == model.Password);

      if (user != null)
      {
         FormsAuthentication.SetAuthCookie(model.UserName, false);
         return RedirectToLocal(returnUrl);
      }
      else
      {
         ModelState.AddModelError("", "Invalid username or password.");
      }
   }

   // If we got this far, something failed, redisplay form
   return View(model);
}

上面的代碼將創建我們的新實例Account DataContext,並檢查與現有用戶匹配的用戶和密碼。如果是這樣,我們將設置一個auth cookie,它將登錄到用戶。

logout

public ActionResult LogOff()
{
   FormsAuthentication.SignOut();
   Session.Abandon();
}

上面的代碼將清除我們之前設置的auth cookie。這將具有將用戶登出系統的效果。

如果我們現在運行該項目,我們現在可以以我們在測試數據中創建的兩家公司之一登錄。所有非常簡單。

現在是多數據庫方法。

我們創建兩個新的數據庫,每個公司都有一個。像我們在測試數據的表格中指定的那樣,調用它們“ Company1”和“ Company2” Account在每一箇中,創建一個新的表格Jobs,如下所示:

在每個數據庫中添加幾個測試作業:

公司1測試數據:

公司2測試數據:

現在回到Visual Studio,創建一個名爲SystemDAL的文件夾 來存儲與實際系統相關的所有數據對象。

首先,創建一個名爲DataContext.cs的新類:

public class DataContext : DbContext
{
   public DataContext(string database)
     : base("Data Source=desktop\\Server2012;Initial Catalog=" + database + ";Integrated Security=True")
   {
   }
   
   public DbSet<Job> Jobs { get; set; }
}

這是我們實現我們的多數據庫邏輯的地方。我們不是將連接字符串的名稱傳遞給DataContext基礎構造函數,而是使用傳遞給DataContext構造函數的數據庫名稱來構建我們自己的這將取自Account我們的數據庫中表格。

創建第二個類來表示一個job對象:

public class Job
{
   public string JobName { get; set; }
   public int Id { get; set; }
}

現在我們將修改該Home\Index()函數來加載當前的用戶數據:

[Authorize]
public ActionResult Index()
{
   // get the current user:
   var accountContext = new AccountDAL.DataContext();
   var user = accountContext.Users.FirstOrDefault(x => x.Email == User.Identity.Name);

   if (user != null)
   {
      // now we have the current user, we can use their Account 
      // to create a new DataContext to access system data:
      var systemContext = new SystemDAL.DataContext(user.Account.Database);
      return View(systemContext.Jobs);
   }
   return View();
}

上面的代碼首先創建我們的一個實例Account DataContext,並獲取一個代表當前登錄用戶的對象。由此,我們可以創建一個System DataContext實例,傳入我們希望連接的數據庫的名稱。

一旦連接起來,我們就可以把所有公司的工作清單都傳遞給了View

修改Index視圖如下,替換現有的代碼:

@model IQueryable<MultiTenancy.SystemDAL.Job>

@{
    ViewBag.Title = "Home Page";
}

<br/>
<ul>
    @if (Model != null)
    {
        foreach (var job in Model)
         {
             <li>@job.JobName</li>
         }
    }
</ul>

我們有它 - 一個多租戶Web應用程序,它將每個用戶的數據存儲在一個單獨的數據庫中!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章