2012-01-19 21 views
2

我正在用EF和DB優先方法構建ASP.NET MVC3網站。我需要爲用戶提供運行時數據庫上下文切換的可靠機制。我有幾個用於遠程「工作室」的數據庫(相同的模式),公司總部的應用程序用戶需要能夠隨時在數據庫之間切換。ASP.NET MVC3實體框架的數據庫切換機制沒有會話使用?

首先,我已實施了基本控制器,即有ChangeDbContext(串DBNAME)。它將選定的dbName保存到Session中,然後我在OnActionExecuting方法中從Session中檢索。然而,事實證明,這是不可靠的,因爲會話表現不可預測(隨機過期等)。所以我正在尋找一種聰明的方式來取代Session與其他東西。

我可以使用的建議: - 往哪裏放的EntityFramework對象初始化(BaseController構造?) - 在那裏,我應該做的,利用與WindowsAuth模擬的數據庫連接任何其他更改?

+0

聽到asp.net會話行爲是不可預知的並隨機過期是令人驚訝的! – chandmk

回答

2

首先,您需要確保您的應用程序會話可以在重新啓動和應用程序池回收後繼續運行。 See this

其次,你需要注入基於經過驗證的用戶請求你的DbContext的連接字符串。

我假設你已經有了一個完整的用戶數據庫,所以你需要做的是保存可能的連接字符串的列表在SQL表,並涉及他們回到他們關聯的用戶帳戶。驗證用戶後,您需要檢索與用戶帳戶關聯的連接字符串。 您不希望將連接字符串存儲在會話或任何其他可能會將敏感數據暴露給Web客戶端的機制中。所以總之這就是你需要做的。

  1. 您將希望檢索您的連接字符串爲每個請求基於經過身份驗證的用戶。
  2. 將連接字符串注入到DBContext中。
  3. 根據需要進行數據庫調用。
  4. 錢!

注射串到實體很容易。

如果您首先使用EF 4.1代碼,則您的DBContext看起來像這樣。 EF 4.1接受普通的ADO.NET連接字符串。

public class ExampleProvider : DbContext, IExampleProvider 
{ 
    private readonly string _nameOrStringConnection; 

    public ExampleProvider() 
    { 

    } 

    public ExampleProvider(string nameOrStringConnection) 
     : base(nameOrStringConnection) 
    { 
     _nameOrStringConnection = nameOrStringConnection; 
    } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     base.OnModelCreating(modelBuilder); 
     modelBuilder.Entity<Example>().ToTable("example"); 
     modelBuilder.Entity<Example>().HasKey(x => x.ExampleId); 
    } 

    public DbSet<Example> Examples { get; set; } 

} 

如果您使用EF.edmx你需要確保你注射的連接字符串包含這樣的EDMX元數據文件信息...

...「元數據=資源:// /ExampleModel.csdl|res:// /ExampleModel.ssdl |資源://*/ExampleModel.msl; ...

如果您在EDMX設計文件看,你會看到你的DBContext有幾個構造函數重載,使用第二個或第三個重載廣告您的需要。

#地區的背景下

/// <summary> 
/// No Metadata Documentation available. 
/// </summary> 
public partial class Entities : ObjectContext 
{ 
    #region Constructors 

    /// <summary> 
    /// Initializes a new Entities object using the connection string found in the 'Entities' section of the application configuration file. 
    /// </summary> 
    public Entities() : base("name=Entities", "Entities") 
    { 
     this.ContextOptions.LazyLoadingEnabled = true; 
     OnContextCreated(); 
    } 

    /// <summary> 
    /// Initialize a new Entities object. 
    /// </summary> 
    public Entities(string connectionString) : base(connectionString, "Entities") 
    { 
     this.ContextOptions.LazyLoadingEnabled = true; 
     OnContextCreated(); 
    } 

    /// <summary> 
    /// Initialize a new Entities object. 
    /// </summary> 
    public Entities(EntityConnection connection) : base(connection, "Entities") 
    { 
     this.ContextOptions.LazyLoadingEnabled = true; 
     OnContextCreated(); 
    } 

    #endregion 
    /// incomplete file 

祝你好運!

+0

謝謝,你的回答是最全面的,我想出了你的建議稍作修改的版本,但這足夠接近並允許獲得想法並朝着正確的方向前進;) – torm

1

Cookie可以持續很長時間,比會話長很多。您還可以查看隱藏的頁面變量或重疊的URL。

+0

謝謝,Cookie看起來不錯,但Cookie集合何時可供閱讀?我猜控制器構造函數是在HttpContext被調用之前執行的,對吧?那麼你會建議把Cookie的閱讀邏輯放在哪裏? – torm

+0

嗨@torm你應該可以在你正在訪問會話對象的任何地方訪問cookie。 – Kane

0

1)會話不會隨機過期...但在您設置了we.config之後...默認值爲10分鐘。 Seesion必須過期,因爲無法知道用戶離開我們的網站......所以如果他們停止訪問頁面,比如說10分鐘,我們假設,他們就會離開......您可以增加這個時間,但問題仍然存在。 2)Tou可以直接將信息存儲在cookie中。現在,由於cookie只會浪費瀏覽器上的資源(空間很小),因此您可以使cookie保持不變......以便永不過期 3)作爲cookie的替代方法,您可以將此信息與用戶的憑證信息一起存儲(登錄名等)您可以使用Profile提供程序來定義屬性DBChosen。